刚找到PHPUnit_Framework_TestCase::any。
返回一个匹配器,当匹配它的方法被执行零次或多次时匹配。
据我所知,方法总是被调用"零次或多次",我从未调用方法-1次或更少次。所以这个匹配器应该始终匹配。为什么会存在以及何时使用它?
答案 0 :(得分:1)
以下是一个小代码示例,其中显示了方法::method()
class SomeClass
{
public function method(){
// smth is being done here;
}
}
class SomeClassTest extends PHPUnit_Framework_TestCase
{
private $mock;
public function setUp(){
$this->mock = $this->getMockBuilder('SomeClass')
->getMock();
}
/**
* @test
*/
public function canStub(){
$this->mock->expects($this->any())
->method('method')
->willReturn(true);
$this->assertTrue($this->mock->method());
}
/**
* @test
*/
public function willCauseFatalError(){
$this->mock->method('method')
->willReturn(true);
$this->assertTrue($this->mock->method());
}
}
第二次测试将给出Fatal error: Call to a member function willReturn() on null
。
更重要的是,如果SomeClass
在method
旁边有任何其他方法,则还需要通过->expects($this->any())...
嘲笑
答案 1 :(得分:0)
该场景基本上是关于一个模拟对象,其中被调用的方法不参与测试场景(可能被调用一次或多次超出了测试用例的范围)。
例如:
{{1}}
希望这个帮助
答案 2 :(得分:0)
class FooTest {
public function testSomething() {
$mock = $this->getMockCollaborator();
$foo = new Foo($mock, false);
// make asserts on $foo with "false" state
// maybe this calls $mock->getName() 4 times
}
public function testAnotherSomething() {
$mock = $this->getMockCollaborator();
$foo = new Foo($mock, true);
// make more asserts on $foo with "true" state
// maybe this calls $mock->getName() 12 times
}
protected function getMockCollaborator() {
$mock = $this->getMock(Collaborator::class);
$mock->expects($this->any())->method('getType')->willReturn(1);
$mock->expects($this->any())->method('getName')->willReturn('Test');
return $mock;
}
}
对于任何特定的测试用例,您可能确切地知道应该调用协作者的方法的次数。但是,在测试用例之间共享模拟协作者通常很方便。当模拟如此共享时,简单地让方法被调用任意次而不是特定次数可能更方便。
为什么要指定调用方法的次数?
三个原因。首先,我们设定了对模拟协作者的期望,以确保被测系统正确地与协作者交互。虽然对通话计数的肆意验证可能是code smell,但在协作者有副作用时进行验证至关重要。例如:
其次,隔离框架可能会更快失败。这是理想的:测试越接近有缺陷的代码越好。这"快速失败" the paper that introduced mock objects中具体讨论了基本原理:
另一方面,模拟实现可以在每次与域代码交互时测试断言,因此更有可能在正确的时间失败并生成有用的消息。这样可以轻松跟踪故障的具体原因,尤其是故障消息还可以描述预期值和实际值之间的差异。例如,在上面的小部件代码中,模拟小部件知道它应该只被轮询一次,并且一旦发生第二次轮询就会失败。
第三,在PHPUnit中,如果模拟类包含一个名为method
的方法,则必须在调用expects
之前专门调用method
。根据{{3}}:
如果原始类确实声明了一个名为"方法"的方法。然后必须使用
$stub->expects($this->any())->method('doSomething')->willReturn('foo');
。
指定any
和不指定规则有什么区别?
在PHPUnit中,没有任何内容:any
是默认状态。 Mockery与其documentation匹配器相同。但是,并非所有隔离框架都遵循此原则。 IIRC,Moq的默认呼叫计数期望为1,如果"任何"适用。