在依赖的PHPUnit测试之间传递的对象会发生什么?

时间:2011-07-25 19:53:39

标签: php mocking phpunit depends

这不是一个问题,而是试图将我浪费在PHPUnit上的时间保存在别人身上。

我的问题是我的模拟对象在依赖测试中使用时没有返回预期值。似乎PHPUnit不会在依赖测试之间保留相同的对象,即使语法使它看起来像它。

有谁知道为什么PHPUnit会这样做?这是一个错误吗?在PHPUnit中这样的事情使得非常令人沮丧地使用。

<?php 
class PhpUnitTest
extends PHPUnit_Framework_TestCase
{
private $mock;

public function setUp()
{
    $this->mock = $this->getMock('stdClass', array('getFoo'));

    $this->mock->expects( $this->any() )
        ->method('getFoo')
        ->will( $this->returnValue( 'foo' ) );
}

public function testMockReturnValueTwice()
{
    $this->assertEquals('foo', $this->mock->getFoo());
    $this->assertEquals('foo', $this->mock->getFoo());

    return $this->mock;
}

/**
 * @depends testMockReturnValueTwice
 */
public function testMockReturnValueInDependentTest($mock)
{
    /* I would expect this next line to work, but it doesn't! */
    //$this->assertEquals('foo', $mock->getFoo());

    /* Instead, the $mock parameter is not the same object as
     * generated by the previous test! */
    $this->assertNull( $mock->getFoo() );
}

}

2 个答案:

答案 0 :(得分:5)

PHPUnit中的模拟对象附加到为其创建的测试实例,根据定义,这意味着单个测试方法。这样做的原因是PHPUnit允许您指定在测试期间必须满足的模拟的期望。为此,一旦方法成功终止,它就会断言这些期望。如果模拟在测试中存在,那么期望就不会起作用。

问题是这不支持存根对象:仅包含响应方法和输入的固定操作的模拟。存根不会验证他们的方法被称为完全模拟可以。也许PHPUnit可以从setUpBeforeClass()中创建与测试实例无关的存根的能力中受益。

您的另一个选择是使用外部模拟对象库,例如MockeryPhake

修改:再次查看示例代码之后,我想知道为什么您会对此行为感到惊讶。正如Shaunak所写,在执行每个测试方法之前,会在新实例上调用setUp()。因此,每个实例都会收到一个新的模拟stdClass。如果只需要一种测试方法来获得期望,请将其添加到测试方法本身中。您仍然可以使用任何应该对所有测试方法都通用的行为在setUp()中创建模拟对象。

答案 1 :(得分:2)

我不是一个php人,所以如果我错了就纠正我,但是所有的单元测试都是按照以下顺序运行的,

设置 - &gt;测试功能 - &gt;破坏。

因此每次执行任何测试功能之前都会调用setup和destroy函数。这样做是为了保持单元测试的目的。

如果你想拥有依赖单元测试用例,那么你必须对它们进行编码,而不是依赖于全局变量来做到这一点(这会破坏单元测试的目的!)。如果存在依赖于某个函数的测试用例'A',则从'A'调用该函数然后断言这些值。