Подтвердить что ты не робот

Любой реальный пример слова о том, как setUp() и tearDown() следует использовать в PHPUnit?

Методы setUp() и tearDown() вызываются до и после каждого теста. Но действительно, есть ли какой-нибудь реальный пример о том, зачем мне это нужно?

Проверяя тесты других людей, я всегда вижу что-то вроде:

public function setUp()
{
    $this->testsub = new TestSubject();
}

public function tearDown()
{
    unset($this->testsub);
}

public function testSomething()
{
    $this->assertSame('foo', $this->testsub->getFoo());
}

Конечно, между этим способом и "старым" локальным переменным практически нет разницы.

4b9b3361

Ответ 1

Если вы выполняете каждый метод тестирования индивидуально, ваш тестовый код будет разделять множество строк, которые просто создают объект для тестирования. Этот общий код может (но не ДОЛЖЕН) перейти к методу настройки.

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

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

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

Таким образом, существует намного больше настроек, чем требуется разрывы, и я всегда удаляю метод teardown, если для этого теста не должно быть сделано.

Что касается макетов, я работаю следующим образом:

private $_mockedService;
private $_object;
protected function setUp()
{
    $this->_mockedService = $this->getMock('My_Service_Class');
    $this->_object = new Tested_Class($this->_mockService);
}

public function testStuff()
{
    $this->_mockedService->expects($this->any())->method('foo')->will($this->returnValue('bar'));
    $this->assertEquals('barbar', $this->_object->getStuffFromServiceAndDouble());
}

Ответ 2

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

Вы можете создавать ресурсы, такие как дескриптор файла в setUp, затем убедитесь, что вы закрываете их в tearDown. Если вы пишете временные файлы, вы можете убедиться, что их удалите. Если вы открываете соединение с базой данных, вы можете закрыть его (хотя вы можете сделать это в другом месте - setupBeforeClass/tearDownAfterClass), которые вызывают для каждого тестового файла, а не для каждого тестового примера.)

Это просто до/после крючка, который есть groovy вещь, чтобы иметь в целом. Используйте его, чтобы сделать вашу жизнь проще или не использовать ее.

Ответ 3

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

Скажем, например, у меня был класс, который собирался рассчитать стоимость доставки по содержимому корзины покупок, определенной тележкой. И пусть говорят, что эта корзина покупок передается в класс расчета доставки через инъекцию зависимости. Чтобы протестировать большинство методов класса, вам может потребоваться фактически создать экземпляр объекта тележки и установить его в классе, чтобы он тестировал ваши различные методы. Вам также может потребоваться добавить предметы в корзину. Поэтому у вас может быть такая настройка:

public function setUp()
{
    $this->cart = new cart();
    $this->cart->add_item('abc');
    $this->cart->add_item('xyz');
}

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

public function tearDown()
    unset($this->cart);
}