Методы setUp()
и tearDown()
вызывают до и после каждого теста. Но действительно, есть ли какой-нибудь реальный пример о том, зачем мне это нужно?
Проверяя тесты других людей, я всегда вижу что-то вроде:
public function setUp() { $this->testsub = new TestSubject(); } public function tearDown() { unset($this->testsub); } public function testSomething() { $this->assertSame('foo', $this->testsub->getFoo()); }
сpublic function setUp() { $this->testsub = new TestSubject(); } public function tearDown() { unset($this->testsub); } public function testSomething() { $this->assertSame('foo', $this->testsub->getFoo()); }
Конечно, практически нет разницы между этим способом и «старым» локальным переменным способом.
Если вы будете выполнять каждый тестовый метод индивидуально, ваш тестовый код будет разделять множество строк, которые просто создают объект для тестирования. Этот общий код может (но не ДОЛЖЕН) перейти к методу настройки.
Все, что нужно сделать для создания объекта, подлежащего тестированию, также входит в метод установки, например создание макетных объектов, которые вводятся в конструктор тестируемого объекта.
Ничего из этого не нужно прокручивать, потому что следующий вызов установки инициализирует переменные-члены класса новым набором объектов.
Единственное, что требует отрыва, – это то, что ваш тест оставляет что-то за собой постоянно, например, созданные файлы или записи в базе данных. На самом деле не очень хорошая идея писать тесты, которые делают такие вещи, но в какой-то момент вы больше не можете абстрагироваться и должны касаться таких вещей, как жесткий диск, база данных или реальная сеть.
Таким образом, существует намного больше настроек, чем требуется отрыв, и я всегда удаляю метод 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()); }
Вы можете создать экземпляр объектов привязки и сделать их доступными как переменные экземпляра в каждом тесте, а не конструировать их отдельно для каждого теста.
Вы можете создавать ресурсы, такие как дескриптор файла в setUp, затем убедитесь, что вы закрываете их в tearDown. Если вы пишете временные файлы, вы можете убедиться, что их удалите. Если вы откроете соединение с базой данных, вы можете закрыть его (хотя вы можете сделать это в другом месте – setupBeforeClass
/ tearDownAfterClass
которые вызывают для каждого тестового файла, а не для каждого тестового примера.)
Это просто до / после крючка, который является отличным делом, чтобы иметь в целом. Используйте его, чтобы сделать вашу жизнь проще или не использовать ее.
Вы можете использовать это почти в любое время, когда у вас будет зависимость в классе, который вы тестируете. Классическим примером этого может быть какой-то объект хранения состояния приложения (объект сеанса, корзина покупок и т. Д.).
Скажем, например, у меня был класс, который собирался рассчитать стоимость доставки содержимого корзины, определенной объектом тележки. И предположим, что эта корзина покупок передается в класс расчета доставки через инъекцию зависимости. Чтобы протестировать большинство методов класса, вам может потребоваться фактически создать экземпляр объекта тележки и установить его в классе, чтобы он тестировал ваши различные методы. Вам также может потребоваться добавить предметы в корзину. Поэтому у вас может быть такая настройка:
public function setUp() { $this->cart = new cart(); $this->cart->add_item('abc'); $this->cart->add_item('xyz'); }
Давайте также предположим, что ваши методы тестирования могут фактически изменить элементы корзины, украсив их информацией о стоимости доставки. Вы не хотите, чтобы информация с одного теста кровоточила в следующий, так что вы просто отменили тележку в конце.
public function tearDown() unset($this->cart); }
сpublic function tearDown() unset($this->cart); }