php 关于在 PHPUnit 中应该如何使用 setUp() 和 tearDown() 的任何真实例子?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13942780/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 06:19:08  来源:igfitidea点击:

Any real word example about how setUp() and tearDown() should be used in PHPUnit?

phpunit-testingtestingphpunit

提问by gremo

Methods setUp()and tearDown()are invoked before and after each test. But really, is there any real word example about why should I need this?

在每次测试之前和之后调用方法setUp()tearDown()。但真的,有没有关于我为什么需要这个的真实例子?

Inspecting other people tests, I always see something like:

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

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

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

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

Of course, there is virtually no difference between this way and the "old" local variable way.

当然,这种方式与“旧”局部变量方式几乎没有区别。

回答by Sven

If you do every test method individually, your test code will share a lot of lines that simply create the object to be tested. This shared code can (but not SHOULD) go into the setup method.

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

Anything that needs to be done to create the object to be tested then also goes into the setup method, for example creating mock objects that are injected into the constructor of the tested object.

创建要测试的对象需要做的任何事情也会进入 setup 方法,例如创建注入到被测试对象的构造函数中的模拟对象。

Nothing of this needs to be teared down because the next call to setup will initialize the class member variables with a new set of objects.

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

The only thing that needs teardown is if your test leaves something behind permanently, like files that got created, or database entries. It really isn't a very good idea to write tests that do such things, but at some point you cannot abstract anymore and have to touch stuff like the harddrive, database or the real network.

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

So there is a lot more setup than teardown needed, and I always delete the teardown method if there is no work to be done for this test.

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

Regarding mocks, I work like this:

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

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

回答by Koobz

You can instantiate a bunch of fixture objects and have them available as instance variables in each test instead of constructing them individually for each test.

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

You can create resources like a file handle in the setUp then make sure you close them in tearDown. If you're writing temporary files, you can make sure you delete them. If you open a database connection, you can close it (though you might want to do that elsewhere - setupBeforeClass/ tearDownAfterClasswhich get called for every test file, not for every test case.)

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

It's just a before/after hook which is a groovy thing to have in general. Use it to make your life easier, or don't use it.

这只是一个前/后钩子,一般来说是一件非常棒的事情。使用它让您的生活更轻松,或者不要使用它。

回答by Nick

There is a memory leak in provided example in accepted answer. You should add tearDown:

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

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

PHPUnit creates new test case object for every test method call. So if there are 4 test method's - there are will be 4 objects, and 4 mockedService's will be created. And they wouldn't removed until the end of the script (entire test suite). So you need to delete all objects and unset all variables in tearDown to prevent memory leak.

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

回答by Mike Brant

You could use this almost anytime you would have a dependency within the class you are testing. A classic example of this might be some sort of object storing application state (a session object, a shopping cart, etc.).

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

Say for example I had a class that was going to calculate shipping costs on the contents of a shopping cart defined by a cart object. And let's say this shopping cart is passed into the shipping calculation class via dependency injection. To test most methods of the class you might need to actually instantiate a cart object and set it in the class in order to unit tests your various methods. You might also need to add items into the cart ass well. So you might might have a setup like this:

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

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

Let's also assume your test methods might actually modify the cart's items, decorating them with shipping cost information. You don;t want information from one test bleeding into the next, so you just unset the cart at the end.

我们还假设您的测试方法实际上可能会修改购物车的商品,用运费信息装饰它们。您不希望从一项测试中获取信息流入下一项,因此您只需在最后取消设置购物车即可。

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