Что происходит с объектами, передаваемыми между зависимыми тестами PHPUnit? - PullRequest
6 голосов
/ 25 июля 2011

Это не столько вопрос, сколько попытка сэкономить кому-то еще час, потраченный на PHPUnit.

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

Кто-нибудь знает, почему PHPUnit делает это?Это ошибка?Подобные вещи в PHPUnit делают его очень разочаровывающим в использовании.

<?php 
class PhpUnitTest
extends PHPUnit_Framework_TestCase
{
private $mock;

public function setUp()
{
    $this->mock = $this->getMock('stdClass', array('getFoo'));

    $this->mock->expects( $this->any() )
        ->method('getFoo')
        ->will( $this->returnValue( 'foo' ) );
}

public function testMockReturnValueTwice()
{
    $this->assertEquals('foo', $this->mock->getFoo());
    $this->assertEquals('foo', $this->mock->getFoo());

    return $this->mock;
}

/**
 * @depends testMockReturnValueTwice
 */
public function testMockReturnValueInDependentTest($mock)
{
    /* I would expect this next line to work, but it doesn't! */
    //$this->assertEquals('foo', $mock->getFoo());

    /* Instead, the $mock parameter is not the same object as
     * generated by the previous test! */
    $this->assertNull( $mock->getFoo() );
}

}

Ответы [ 2 ]

5 голосов
/ 26 июля 2011

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

Проблема в том, что это не поддерживает объекты-заглушки: макеты, которые содержат только стандартные действия, которые необходимо выполнить в ответ на методы и входные данные. Заглушки не подтверждают, что их методы вызываются как полные ложные показания. Возможно, PHPUnit мог бы извлечь выгоду из возможности создавать заглушки в setUpBeforeClass(), которые не привязаны к тестовому экземпляру.

Другой вариант - использовать внешнюю библиотеку фиктивных объектов, такую ​​как Насмешка или Phake .

Редактировать: После повторного просмотра вашего примера кода, я удивляюсь, почему вы удивляетесь такому поведению. Как писал Шаунак, setUp() вызывается в новом экземпляре перед выполнением каждого метода тестирования. Таким образом, каждый экземпляр получает новый макет stdClass. Если вы хотите, чтобы только один тестовый метод получил ожидание, добавьте его внутри самого тестового метода. Вы все еще можете создать фиктивный объект в setUp() с любым поведением, которое должно быть общим для всех методов тестирования.

2 голосов
/ 26 июля 2011

Я не php парень, так что поправьте меня, если я ошибаюсь, но все юнит-тесты предназначены для запуска в следующей последовательности:

Настройка -> Функция тестирования -> уничтожить.

поэтому функция setup и destroy вызывается каждый раз перед выполнением любой тестовой функции.Это сделано с целью сохранения цели модульного тестирования.

Если вы хотите иметь зависимые блок-тесты, вы должны их кодировать, вместо того, чтобы делать это в зависимости от глобальных переменных (это противоречит цели модульных тестов!).Если есть тестовый пример «A», который зависит от какой-либо функции, вызовите эту функцию из «A», а затем подтвердите значения.

...