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

依赖PHPUnit测试之间传递的对象会发生什么情况?,php,mocking,phpunit,depends,Php,Mocking,Phpunit,Depends,这与其说是一个问题,不如说是一个试图拯救别人的问题,我只是在PHPUnit上浪费了一个小时 我的问题是,在依赖测试中使用模拟对象时,没有返回预期值。看来PHPUnit在依赖测试之间并没有保留相同的对象,即使语法使它看起来像是这样 有人知道PHPUnit为什么这样做吗?这是虫子吗?在PHPUnit中,这样的事情不会使它使用起来非常令人沮丧 <?php class PhpUnitTest extends PHPUnit_Framework_TestCase { private $mock;

这与其说是一个问题,不如说是一个试图拯救别人的问题,我只是在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() );
}

}

我不是php爱好者,如果我错了,请纠正我,但是所有单元测试都是按以下顺序运行的

设置-->测试功能-->销毁

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


如果您想拥有相关的单元测试用例,那么您必须对它们进行编码,而不是依赖全局变量来完成(这违背了单元测试的目的!)。如果存在依赖于某个函数的测试用例“a”,则从“a”调用该函数,然后断言值

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

问题是它不支持存根对象:只包含为响应方法和输入而采取的固定动作的模拟。存根不会验证它们的方法是否像完整模拟一样被调用。也许PHPUnit可以受益于在
setUpBeforeClass()
中创建未绑定到测试实例的存根的功能

另一个选项是使用外部模拟对象库,如或


编辑:再次查看示例代码后,我想知道为什么您会对这种行为感到惊讶。正如Shaunak所写的那样,在执行每个测试方法之前,对新实例调用
setUp()
。因此,每个实例接收一个新的mock
stdClass
。如果只希望一个测试方法接收期望值,请将其添加到测试方法本身中。您仍然可以在
setUp()
中创建模拟对象,其行为应为所有测试方法所共有的行为。

遇到问题时,请添加调用phpunit的命令行。--有什么理由让
$mock
成为私有成员吗?AFAIK phpunit在每次测试之前都运行setUp()方法,这样重置$this->mock的值,我想这会像你写的那样起作用
不会被@dependent测试调用,所以我真的很惊讶这也失败了。。。如果我把一个mock传递给一个我用@dependens:)传递的类,这可能会让我很痛苦@itom99:是的,我本来希望$this->mock会被重置,但是仔细看看代码:在testMockReturnValueInDependentTest()中,mock对象作为局部变量传入。@hakre:你想知道我为什么要把$this->mock private,或者为什么我把它作为一个实例变量(而不是本地变量)?destroy方法的名称是
tearDown()
。这是正确的!抱歉,我只是笼统地说。所以换句话来说:在每次测试之后,在该测试运行中创建的所有模拟对象都会被剥夺其所有分配的
expect
ations?@David:我感到困惑的原因是语法使dependee的返回值看起来像是传递给depender的。如果PHPUnit从头开始重建一切,那么为什么它首先会提供这种误导性的语法?@edorian-这些期望是经过验证的,但似乎没有被剥夺。这发生在测试方法成功完成之后,但在调用
tearDown()
之前。虽然您可以在
tearDown()
中向模拟添加更多期望和调用,但这并不是很有用。@Ian-Ah,我没有看到您将模拟传递到下一个测试。虽然它的一些期望值可能会起作用——用()断言传递给
的参数值,并执行
will()
中指定的操作——但不会验证调用计数期望值,因为传递给依赖方法的模拟值未附加到它的测试用例实例。您可以在mock对象上调用
\uu phpunit\u verify()
,但这是徒劳的。有关详细信息,请参见PHPUnit\u Framework\u TestCase::verifyMockObjects()
:每个模拟都经过验证和清理。深入挖掘,看看这会带来什么。@Ian-依赖方法中注释掉的调用失败告诉我
\uu phpunit\u cleanup()
必须删除
getFoo()
期望值。