Любой реальный пример слова о том, как 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());
}
Конечно, между этим способом и "старым" локальным переменным практически нет разницы.
Ответы
Ответ 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);
}