类:
class TestMe
{
public function m1 (array &$a)
{
}
public function m2 (array &$a)
{
}
public function methodd()
{
$a = array();
$this->m1 ($a);
$this->m2 ($a);
return $a;
}
}
试验:
class X extends PHPUnit_Framework_TestCase
{
public function testMethod()
{
$mock = $this->getMock('TestMe', array('m1','m2'));
$mock->expects($this->once())->method('m1')->with(array())->willReturnCallback(function (&$x) { $x['a'] = 1; });
$mock->expects($this->once())->method('m2')->with(array('a' => 1))->willReturnCallback(function (&$x) { $x['b'] = 2; });
$x = $mock->methodd();
$this->assertEquals (array('a' => 1, 'b' => 2), $x);
}
}
不知何故失败了:
有1次失败:
1)X :: testMethod 方法名称的期望失败等于1次调用时。 调用TestMe :: m1(Array(...))的参数0与预期值不匹配。 声明两个数组相等的失败。 ---期待 +++实际 @@ @@ 阵列( +'a'=> 1 +'b'=> 2 )
FAILURES! 测试:1,断言:2,失败:1。
我不知道它可能是什么。换句话说,我想修改一个“引用”参数,并检查它:)
答案 0 :(得分:1)
问题不在于willReturnCallback()
。你的问题是你通过引用传递东西。如果查看失败消息,它会告诉您传递给方法m1
的参数与预期的不匹配。这是说数组不是空的。
运行测试后,PHPUnit会检查模拟器上的参数调用。因此它存储了方法调用中使用的参数的副本。在回调中,您指的是变量的引用。因此PHPUnit在mock中存储自己的引用副本以进行检查。在后续调用函数时,变量不仅会更新,而且还会存储PHPUnit存储的值。因此,当它检查使用适当的参数调用模拟时,它会根据参考中存储的值(即最终值)而不是最初使用的值进行检查。
要解决此问题,请将测试更改为:
public function testMethod()
{
//Get a copy of the testcase to use in the callback
$testcase = $this;
$mock = $this->getMock('TestMe', array('m1','m2'));
$mock->expects($this->once())
->method('m1')
->willReturnCallback(function (&$x) use ($testcase) {
//do your parameter checking immediately
$testcase->assertEquals(array(), $x);
$x['a'] = 1;
});
$mock->expects($this->once())
->method('m2')
->willReturnCallback(function (&$x) use ($testcase) {
//do your parameter checking immediately
$testcase->assertEquals(array('a' => 1), $x);
$x['b'] = 2;
});
$x = $mock->methodd();
$this->assertEquals (array('a' => 1, 'b' => 2), $x);
}
虽然是IMO,但您不应该嘲笑作为您正在测试的类的一部分的代码。 methodd()
使用这些函数的事实是您的类的实现细节。如果您决定将m1()
或m2
中的逻辑移到methodd()
,那么您的测试应该通过。模拟这些方法会使您的测试变得不那么有用。它们可能由于类中的代码更改而失败,而不是功能/错误的实际更改。
无论如何,针对您的具体问题的修复方法是检查回调中的参数值,而不是使用with()
。