下面是代码示例
<?php
interface iFS
{
public function read();
public function write($data);
}
class MyClass
{
protected $_fs = null;
public function __construct(iFS $fs)
{
$this->_fs = $fs;
}
public function run(array $list)
{
foreach ($list as $elm)
{
$this->_fs->write($elm);
}
return $this->_fs->read();
}
}
class MyTests extends PHPUnit_Framework_TestCase
{
public function testFS()
{
$mock = $this->getMock('iFS');
$mock->expects($this->at(0))
->method('read')
->will($this->returnValue('tototatatiti'));
$c = new MyClass($mock);
$result = $c->run(array('toto', 'tata', 'titi'));
$this->assertEquals('tototatatiti', $result);
}
}
这绝对不是一个真实的情况,但它会发生一些奇怪的phpunit和at($index)特性。
我的问题很简单,测试失败是正常的吗?
我明确要求返回"tototatatiti",但它从未发生…
时- 我删除了$this->_fs->write($elm);或
- 我取代模拟->预计美元($ this ->(0))通过模拟->预计美元($ this ->一次())
测试通过到绿色
有什么我不明白的吗?
编辑:模拟->预计美元($ this -> (3))->方法("读")-> ($ this -> returnValue (' tototatatiti '));
=>
根据PHPUnit源代码,我们有:
public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
{
$this->currentIndex++;
return $this->currentIndex == $this->sequenceIndex;
}
每次PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex
尝试匹配调用时,受保护的变量$currentIndex
被增加,因此您首先调用write使其变为0,然后它不匹配read
。
对read
的第二次调用使值变为1,因此它也不匹配。
看起来确实适用于整个对象,如果您需要确保一系列调用以特定顺序发生,这是有用的。
例如,假设write
方法只被调用一次,您可以像这样:$mock->expects($this->at(0))
->method('write');
$mock->expects($this->at(1))
->method('read')
->will($this->returnValue('tototatatiti'));
确保write
方法确实在read
方法之前被调用。
我认为phpunit at()功能是没有用的存根不同的返回结果的模拟方法,如果模拟对象包含一些其他的方法调用太…
如果你想测试如下内容:
$stub->expects($this->at(0))
->method('read')
->will($this->returnValue("toto"));
$stub->expects($this->at(1))
->method('read')
->will($this->returnValue("tata"));
你最好使用像
这样的字符$stub->expects($this->exactly(2))
->method('read')
->will($this->onConsecutiveCalls("toto", "tata));