PHPUnit “Mocked method 不存在”。当使用 $mock->expects($this->at(...))

2022-08-30 12:15:40

我在PHPUnit模拟对象中遇到了一个奇怪的问题。我有一个应该调用两次的方法,所以我使用的是“at”匹配器。这是第一次调用该方法,但由于某种原因,第二次调用它时,我得到“Mocked方法不存在”。我以前使用过“at”匹配器,从未遇到过这种情况。

我的代码看起来像这样:

class MyTest extends PHPUnit_Framework_TestCase
{
    ...

    public function testThis()
    {
        $mock = $this->getMock('MyClass', array('exists', 'another_method', '...'));
        $mock->expects($this->at(0))
             ->method('exists')
             ->with($this->equalTo('foo'))
             ->will($this->returnValue(true));

        $mock->expects($this->at(1))
             ->method('exists')
             ->with($this->equalTo('bar'))
             ->will($this->returnValue(false));
    }

    ...
}

当我运行测试时,我得到:

Expectation failed for method name is equal to <string:exists> when invoked at sequence index 1.
Mocked method does not exist.

如果我删除第二个匹配器,则不会收到错误。

以前有人遇到过这种情况吗?

谢谢!


答案 1

问题最终出在我如何理解“at”匹配器的工作上。此外,我的例子不是逐字逐句地在我的单元测试中。我认为“at”匹配器计数器在每个查询的基础上工作,而它实际上在每个对象实例的基础上工作。

例:

class MyClass {

    public function exists($foo) {
        return false;
    }

    public function find($foo) {
        return $foo;
    }
}

不對:

class MyTest extends PHPUnit_Framework_TestCase
{

    public function testThis()
    {
        $mock = $this->getMock('MyClass');
        $mock->expects($this->at(0))
             ->method('exists')
             ->with($this->equalTo('foo'))
             ->will($this->returnValue(true));

        $mock->expects($this->at(0))
             ->method('find')
             ->with($this->equalTo('foo'))
             ->will($this->returnValue('foo'));

        $mock->expects($this->at(1))
             ->method('exists')
             ->with($this->equalTo('bar'))
             ->will($this->returnValue(false));

        $this->assertTrue($mock->exists("foo"));
        $this->assertEquals('foo', $mock->find('foo'));
        $this->assertFalse($mock->exists("bar"));
    }

}

正确:

class MyTest extends PHPUnit_Framework_TestCase
{

    public function testThis()
    {
        $mock = $this->getMock('MyClass');
        $mock->expects($this->at(0))
             ->method('exists')
             ->with($this->equalTo('foo'))
             ->will($this->returnValue(true));

        $mock->expects($this->at(1))
             ->method('find')
             ->with($this->equalTo('foo'))
             ->will($this->returnValue('foo'));

        $mock->expects($this->at(2))
             ->method('exists')
             ->with($this->equalTo('bar'))
             ->will($this->returnValue(false));

        $this->assertTrue($mock->exists("foo"));
        $this->assertEquals('foo', $mock->find('foo'));
        $this->assertFalse($mock->exists("bar"));
    }

}

答案 2

仅供参考,不确定它是否相关,但我遇到了同样的事情,但不是方法,对我来说它是方法。$this->at()$this->never()

这引发了错误

$mock->expects($this->never())
    ->method('exists')
    ->with('arg');

这修复了错误

$mock->expects($this->never())
    ->method('exists');  

它在使用该方法时执行了相同的操作。$this->exactly(0)

希望这可以帮助某人。


推荐