Тестирование абстрактных классов - PullRequest
136 голосов
/ 10 октября 2008

Как проверить конкретные методы абстрактного класса с помощью PHPUnit?

Я ожидаю, что мне придется создать какой-то объект как часть теста. Хотя я не знаю, как это лучше всего делать, или если PHPUnit допускает это.

Ответы [ 6 ]

228 голосов
/ 11 февраля 2010

Модульное тестирование абстрактных классов не обязательно означает тестирование интерфейса, поскольку у абстрактных классов могут быть конкретные методы, и эти конкретные методы могут быть протестированы.

При написании некоторого библиотечного кода не редкость иметь определенный базовый класс, который вы ожидаете расширить на уровне приложения. И если вы хотите убедиться, что код библиотеки протестирован, вам нужны средства для 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());
    }
}

Макет объекта дает вам несколько вещей:

  • вы не обязаны иметь конкретную реализацию абстрактного класса, и вместо этого можете использовать заглушку
  • Вы можете вызывать конкретные методы и утверждать, что они работают правильно
  • если конкретный метод опирается на не реализованный (абстрактный) метод, вы можете заглушить возвращаемое значение с помощью метода will () PHPUnit
36 голосов
/ 14 февраля 2011

Хороший вопрос. Я тоже искал это.
К счастью, в 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
20 голосов
/ 20 февраля 2018

Следует отметить, что с 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
}
1 голос
/ 23 сентября 2009

Нельсон ответил неправильно.

Абстрактные классы не требуют, чтобы все их методы были абстрактными.

Реализованные методы - это те, которые нам нужно протестировать.

То, что вы можете сделать, - это создать в файле модульного теста поддельный класс-заглушку, расширить его абстрактный класс и, конечно, реализовать только то, что требуется без какой-либо функциональности, и протестировать его.

Приветствие.

1 голос
/ 12 ноября 2008

Эран, ваш метод должен работать, но он идет вразрез с тенденцией написания теста перед фактическим кодом.

Я бы предложил написать тесты на желаемую функциональность неабстрактного подкласса рассматриваемого абстрактного класса, затем написать абстрактный класс и реализующий подкласс и, наконец, запустить тест.

Ваши тесты должны явно проверять определенные методы абстрактного класса, но всегда через подкласс.

0 голосов
/ 12 ноября 2008

Если вы не хотите создавать подкласс абстрактного класса просто для того, чтобы выполнить модульное тестирование методов, которые уже реализованы в абстрактном классе, вы можете попытаться выяснить, позволяет ли ваша структура mock abstract классы.

...