当使用$ 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吗? 嘲笑一个类/接口而不包含它时,我有一些未定义的方法错误。