当使用$ mock-> expect($ this-> at(…))时,PHPUnit“Mocked方法不存在”

我遇到了PHPUnit模拟对象的一个​​奇怪的问题。 我有一个方法应该被调用两次,所以我使用“在”匹配。 这是第一次调用方法,但由于某种原因,第二次调用方法,我得到了“模拟方法不存在”。 我之前使用过“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)); } ... } 

当我运行testing时,我得到:

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

如果我删除第二个匹配器,我没有得到错误。

有没有人遇到过这个?

谢谢!

这个问题最终与我如何理解“在”匹配工作。 另外,我的例子不是逐字的,在我的unit testing中是如何的。 我认为“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")); } } 

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

这提出了错误

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

这修正了错误

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

当使用$this->exactly(0)方法时,它做了同样的事情。

希望这可以帮助别人。

尝试改变$this->at(1) to $this->at(2)

这是PHPUnit错误消息的一个不幸的措辞。

仔细检查您的电话的顺序,就像@ rr的回答提及。

对我而言,据我所知,我自己的代码,我应该分别at(0)at(1) ,但直到我用at(2)at(3)而不是它的工作。 (我在CakePHP中使用会话模拟。)

检查订单的最好方法是进入被调用的方法并检查通过的内容。 你可以这样做:

 $cakePost = $this->getMock('CakePost'); $cakePost->expects($this->once()) ->method('post') ->with( // Add a line like this for each arg passed $this->callback(function($arg) { debug("Here's what was passed: $arg"); }) ); 

据我可以告诉从Demo代码它应该工作。 如果你正在运行一个较旧的PHPUnit版本,并且想要检查是否适用于你,那么我就制作了一个工作示例。

如果没有帮助,也许你可以提供更多(最好的可执行文件)代码? 🙂

 <?php 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('exists') ->with($this->equalTo('bar')) ->will($this->returnValue(false)); $this->assertTrue($mock->exists("foo")); $this->assertFalse($mock->exists("bar")); } } class MyClass { public function exists($foo) { return false; } } 

印花

 phpunit MyTest.php PHPUnit 3.4.15 by Sebastian Bergmann. . Time: 0 seconds, Memory: 4.25Mb OK (1 test, 3 assertions) 

你确定你在testing中包含了MyClass吗? 嘲笑一个类/接口而不包含它时,我有一些未定义的方法错误。