有关于如何在 PHPUnit 中使用 setUp() 和tearDown() 的真实例子吗?

问题描述 投票:0回答:5

方法

setUp()
tearDown()
在每次测试之前和之后调用。但实际上,有没有任何真实的例子说明我为什么需要这个?

检查其他人的测试,我总是看到类似的东西:

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

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

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

当然,这种方式和“旧的”局部变量方式实际上没有什么区别。

php unit-testing testing phpunit
5个回答
34
投票

如果您单独执行每个测试方法,您的测试代码将共享许多行,这些行只是创建要测试的对象。该共享代码可以(但不应该)进入设置方法。

创建要测试的对象所需执行的任何操作也都会进入 setup 方法,例如创建注入到被测试对象的构造函数中的模拟对象。

这一切都不需要拆除,因为下一次调用 setup 将使用一组新的对象初始化类成员变量。

唯一需要拆卸的是您的测试是否永久留下了某些内容,例如创建的文件或数据库条目。编写执行此类操作的测试确实不是一个好主意,但在某些时候您无法再抽象,并且必须接触硬盘驱动器、数据库或真实网络等内容。

因此,需要的设置比拆卸要多得多,如果此测试没有工作要做,我总是删除拆卸方法。

关于模拟,我是这样工作的:

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

4
投票

您可以实例化一堆固定装置对象,并在每个测试中将它们用作实例变量,而不是为每个测试单独构造它们。

您可以在setUp中创建文件句柄等资源,然后确保在tearDown中关闭它们。如果您正在写入临时文件,请确保删除它们。如果您打开数据库连接,则可以关闭它(尽管您可能想在其他地方执行此操作 -

setupBeforeClass
/
tearDownAfterClass
,每个测试文件都会调用它,而不是每个测试用例。)

这只是一个之前/之后的钩子,总的来说这是一个很棒的东西。使用它可以让您的生活更轻松,否则就不要使用它。


2
投票

接受的答案中提供的示例存在内存泄漏。 您应该添加拆解:

protected function tearDown()
{
    $this->_mockedService = null;
}

PHPUnit 为每个测试方法调用创建新的测试用例对象。因此,如果有 4 个测试方法 - 将有 4 个对象,并且将创建 4 个模拟服务。并且直到脚本(整个测试套件)结束时它们才会被删除。 所以需要在tearDown中删除所有对象并取消设置所有变量以防止内存泄漏。


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
投票

在我看来,如果您的测试不高复杂性,您不需要拆卸后测试方法功能,因为之前的测试设置可以完成所有必需的操作,但例如实际情况可能会在每次测试后在数据库中保存该测试的一些记录、结果等,甚至发送电子邮件或更深入的 CI/CD 操作,或使用 api 为失败的测试功能的开发人员所有者分配任务,例如人工智能信息,或者在特定测试通过或未能执行特定操作或创建报告后使用其他相关工具。但在我看来,在设置中添加

this->x = 1
并在拆卸中取消设置它看起来不是真实的例子

© www.soinside.com 2019 - 2024. All rights reserved.