2012-12-18 24 views
21

在每次测试之前和之后调用方法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()); 
} 

当然,也几乎是这样的,“旧”的局部变量的方式没有什么区别。

+0

所不同的是,你只需要设置一次代码,无论多少测试,我们在您的测试类 –

+0

@MarkBaker所以...只是当创建测试主题需要很多行时,例如? – gremo

+0

一个很好的例子就是设置一个数据库表并在完成测试后再次销毁它。 – busypeoples

回答

16

如果您单独执行每个测试方法,您的测试代码将共享很多简单地创建要测试的对象的行。这个共享代码可以(但不应该)进入设置方法。即需要做来创建对象

任何待然后测试也进入设置方法,例如创建被注入到测试对象的构造模拟对象。需要被撕开了,因为设置的下一次调用将一组新的对象初始化类的成员变量

没有这一点。

需要拆除的唯一的事情是,如果你的测试离开背后的东西永远,就像得到了创建的文件或数据库条目。这真的是不写的是做这样的事情测试一个很好的想法,但在某些时候,你不能再抽象,并有触摸的东西,如硬盘,数据库或实际网络。

所以有比需要拆卸有更多的设置,我总是删除的拆卸方法,如果没有这个测试工作要做。

关于嘲弄,我的工作是这样的:

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()); 
} 
+1

感谢您对'tearDown()'的澄清... – gremo

+0

tearDown()在这里是缺少的,但基本上你会解除任何需要清除的东西,类似于desctructor 。 –

+1

@StevenScott没有,'拆解()'是不是故意在我的代码,因为'设置()'无论如何都会覆盖任何东西。无需编写一个将NULL写入该测试类的任何私有属性的拆卸函数。 – Sven

4

您可以实例化一堆灯具对象,并在每次测试中将它们作为实例变量使用,而不是为每个测试单独构建它们。

您可以在setUp中创建类似文件句柄的资源,然后确保在tearDown中关闭它们。如果你正在编写临时文件,你可以确保你删除它们。如果你打开一个数据库连接,你可以关闭它(尽管你可能在想这样做,其他地方 - setupBeforeClass/tearDownAfterClass它被调用每一个测试文件,而不是为每个测试用例)

这只是一个前/挂机后这是一般的常规事情。用它来使你的生活更轻松,或者不使用它。

+2

+1“使用它可以使您的生活更轻松,或者不使用它。” setUp()只是一个重构工具,用于共享_common_代码。只有在有意义时才使用它;不要强制所有灯具的制作进行,因为每个测试都需要一个稍微不同的灯具! –

1

几乎在任何时候您都可以在您正在测试的课程中使用该依赖项。一个经典的例子可能是某种存储应用程序状态的对象(会话对象,购物车等)。

举例说,我有一个班级计算购物车对象定义的购物车内容的运费。假设这个购物车通过依赖注入传递到运输计算类中。要测试该类的大多数方法,您可能需要实际实例化一个购物车对象并将其设置在类中,以便对各种方法进行单元测试。您可能还需要将物品添加到购物车中。所以,你可能会有这样的设置:

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

让我们假设你的测试方法实际上可能会改变购物车的物品,与运输成本信息装饰他们。您不希望一次测试的信息流入下一个测试,所以您最后只需将购物车取消。

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

您需要实例化购物车的MOCK,它将返回您在班级中测试计算所需的值。设置一个真正的购物车可能太复杂,因为它有自己的依赖关系,而且你无法测试购物车是否被正确的参数和方法调用。 – Sven

+0

@Sven我会同意一个模拟车实际上是最好的。我想简单地说明,会给一个想法,以安装程序的'实用程序的使用情况()'和'拆解()',而无需引入更先进的单元测试的概念。也许我没有在这里选择最好的例子:) –

相关问题