Тестирование абстрактных классов
Как проверить конкретные методы абстрактного класса с помощью PHPUnit?
Я бы ожидал, что мне придется создать какой-то объект в рамках теста. Хотя, я не знаю, что лучше для этого, или если PHPUnit позволяет это.
Ответы
Ответ 1
Групповое тестирование абстрактных классов не обязательно означает тестирование интерфейса, поскольку абстрактные классы могут иметь конкретные методы, и эти конкретные методы могут быть протестированы.
Не так уж редко, когда вы пишете некоторый код библиотеки, чтобы иметь определенный базовый класс, который вы ожидаете расширить на своем прикладном уровне. И если вы хотите убедиться, что код библиотеки протестирован, вам нужны средства UT для конкретных методов абстрактных классов.
Лично я использую PHPUnit, и он имеет так называемые заглушки и макеты объектов, которые помогут вам протестировать такие вещи.
Прямо от Руководство 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 object дает вам несколько вещей:
- у вас нет необходимости иметь конкретную реализацию абстрактного класса и вместо этого может уйти с заглушкой
- вы можете вызывать конкретные методы и утверждать, что они выполняются правильно
- Если конкретный метод зависит от нереализованного (абстрактного) метода, вы можете заглушить возвращаемое значение с помощью метода will() PHPUnit
Ответ 2
Это хороший вопрос. Я тоже искал это.
К счастью, PHPUnit уже имеет getMockForAbstractClass()
для этого случая, например
protected function setUp()
{
$stub = $this->getMockForAbstractClass('Some_Abstract_Class');
$this->_object = $stub;
}
Важный:
Обратите внимание, что для этого требуется PHPUnit> 3.5.4. В предыдущих версиях произошла ошибка.
Чтобы перейти на новую версию:
sudo pear channel-update pear.phpunit.de
sudo pear upgrade phpunit/PHPUnit
Ответ 3
Следует отметить, что с PHP 7 была добавлена поддержка анонимных классов. Это дает вам дополнительную возможность для настройки теста для абстрактного класса, который не зависит от функциональных возможностей 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
}
Ответ 4
Эран, ваш метод должен работать, но это противоречит тенденции написания теста перед фактическим кодом.
Я бы предложил написать ваши тесты по желаемой функциональности не абстрактного подкласса рассматриваемого абстрактного класса, затем написать как абстрактный класс, так и внедряющий подкласс и, наконец, запустить тест.
Ваши тесты должны, очевидно, проверять определенные методы абстрактного класса, но всегда через подкласс.
Ответ 5
Ответ Нельсона неверен.
Абстрактные классы не требуют, чтобы все их методы были абстрактными.
Реализованные методы - те, которые нам нужно проверить.
Что вы можете сделать, так это создать поддельный класс-заглушку в файле unit test, расширить его абстрактный класс и реализовать только то, что требуется без каких-либо функций вообще, и проверить это.
Приветствия.
Ответ 6
Если вы не хотите подклассифицировать абстрактный класс просто для выполнения unit test методов, которые уже реализованы в абстрактном классе, вы можете попытаться выяснить, позволяет ли ваша структура mock абстрактные классы.