Вопрос

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

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

Это было полезно?

Решение

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

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

Лично я использую 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

Другие советы

Это хороший вопрос. Я тоже искал это.
К счастью, в 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

Следует отметить, что начиная с 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
}

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

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

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

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

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

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

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

Ваше здоровье.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top