Jak przetestować konkretne metody klasy abstrakcyjnej za pomocą PHPUnit?
Spodziewałbym się, że będę musiał stworzyć jakiś obiekt w ramach testu. Chociaż nie mam pojęcia, jaka jest najlepsza praktyka w tym zakresie lub czy PHPUnit na to pozwala.
Jak przetestować konkretne metody klasy abstrakcyjnej za pomocą PHPUnit?
Spodziewałbym się, że będę musiał stworzyć jakiś obiekt w ramach testu. Chociaż nie mam pojęcia, jaka jest najlepsza praktyka w tym zakresie lub czy PHPUnit na to pozwala.
Odpowiedzi:
Testowanie jednostkowe klas abstrakcyjnych nie musi oznaczać testowania interfejsu, ponieważ klasy abstrakcyjne mogą mieć konkretne metody, a te konkretne metody można testować.
Podczas pisania kodu biblioteki nie jest tak rzadkie, że istnieje pewna klasa bazowa, którą można rozszerzyć w warstwie aplikacji. A jeśli chcesz mieć pewność, że kod biblioteki jest testowany, potrzebujesz środków do UT konkretnych metod klas abstrakcyjnych.
Osobiście używam PHPUnit i ma on tak zwane obiekty pośredniczące i makiety, które pomagają w testowaniu tego rodzaju rzeczy.
Prosto z instrukcji PHPUnit :
abstract class AbstractClass
{
public function concreteMethod()
{
return $this->abstractMethod();
}
public abstract function abstractMethod();
}
class AbstractClassTest extends PHPUnit_Framework_TestCase
{
public function testConcreteMethod()
{
$stub = $this->getMockForAbstractClass('AbstractClass');
$stub->expects($this->any())
->method('abstractMethod')
->will($this->returnValue(TRUE));
$this->assertTrue($stub->concreteMethod());
}
}
Mock obiekt daje kilka rzeczy:
To dobre pytanie. Też tego szukałem.
Na szczęście PHPUnit ma już getMockForAbstractClass()
metodę na ten przypadek, np
protected function setUp()
{
$stub = $this->getMockForAbstractClass('Some_Abstract_Class');
$this->_object = $stub;
}
Zauważ, że wymaga to PHPUnit> 3.5.4. W poprzednich wersjach wystąpił błąd .
Aby zaktualizować do najnowszej wersji:
sudo pear channel-update pear.phpunit.de
sudo pear upgrade phpunit/PHPUnit
Należy zauważyć, że od PHP 7 dodano obsługę klas anonimowych . Daje to dodatkową możliwość skonfigurowania testu dla klasy abstrakcyjnej, takiej, która nie zależy od funkcji specyficznych dla PHPUnit.
class AbstractClassTest extends \PHPUnit_Framework_TestCase
{
/**
* @var AbstractClass
*/
private $testedClass;
public function setUp()
{
$this->testedClass = new class extends AbstractClass {
protected function abstractMethod()
{
// Put a barebones implementation here
}
};
}
// Put your tests here
}
Eran, twoja metoda powinna działać, ale jest sprzeczna z tendencją pisania testu przed rzeczywistym kodem.
Sugerowałbym, aby napisać testy na pożądanej funkcjonalności nieabstrakcyjnej podklasy danej klasy abstrakcyjnej, a następnie napisać zarówno klasę abstrakcyjną, jak i podklasę implementującą, a na koniec uruchomić test.
Twoje testy powinny oczywiście testować zdefiniowane metody klasy abstrakcyjnej, ale zawsze za pośrednictwem podklasy.
Odpowiedź Nelsona jest błędna.
Klasy abstrakcyjne nie wymagają, aby wszystkie ich metody były abstrakcyjne.
Zaimplementowane metody to te, które musimy przetestować.
To, co możesz zrobić, to utworzyć fałszywą klasę pośredniczącą w pliku testu jednostkowego, rozszerzyć klasę abstrakcyjną i zaimplementować tylko to, co jest wymagane, bez żadnej funkcjonalności, oczywiście, i przetestować to.
Twoje zdrowie.
Jeśli nie chcesz tworzyć podklasy klasy abstrakcyjnej tylko po to, aby wykonać test jednostkowy metod, które są już zaimplementowane w klasie abstrakcyjnej, możesz spróbować sprawdzić, czy Twój framework pozwala na mockowanie klas abstrakcyjnych.