【问题标题】:php mock ->expects() does NOT report an error when not calledphp mock ->expects() 不调用时不报错
【发布时间】:2017-07-22 17:18:44
【问题描述】:

我有以下模拟对象:

$permutator = $this->getMockBuilder('PermutationClass', 
array('get_permutation'))->disableOriginalConstructor()->getMock();

$permutator->expects($this->at(0))
                  ->method('get_permutation')
                  ->will($this->returnCallback(function($praram1) {
                        return true;
                  }));
$permutator->expects($this->at(1))
                  ->method('get_permutation')
                  ->will($this->returnCallback(function($praram1) {
                        return true;
                  }));

但是,我的经验是,如果由于某种原因“1”处的调用从未被执行,那么就不会报告关于从未满足期望的错误。

如果我添加以下代码:就在期望之前:

$permutator->expects($this->exactly(2))->method('get_permutation');

然后发生的情况是,如果从未调用给定的期望,则会报告错误。但是,这里发生的情况是,由于某种原因,这使得模拟对象的返回值为 NULL,因为我没有设置它。如果我这样设置:

$permutator->expects($this->exactly(2))->method('get_permutation')->will($this->returnValue("THIS SHOULD NEVER BE RETURNED"));

然后 this 成为该函数的所有预期方法调用的返回值。所以 at(0) 和 at(1) 确实被执行了(我设置了一些打印语句)但是返回值被这个覆盖了:

$permutator->expects($this->exactly(2))->method('get_permutation');

我设法通过以下方式获得预期的行为:

$permutator->expects($this->exactly(2))
           ->method('get_permutation')
           ->will( $this->onConsecutiveCalls(
                       $this->returnCallback(function($praram1) {
                           return true;
                       }),
                       $this->returnCallback(function($praram1) {
                           return false;
                       })
                   )
           );

我的意思是,当我明确设定期望时,为什么模拟对象不会抱怨说 $this->at(1) 永远不会被调用?

【问题讨论】:

  • 您确定没有调用该方法吗?我使用 $this->at() 做了一个简单的示例,如果该方法仅调用一次,则测试失败。我认为您的代码中还有其他内容。

标签: php unit-testing mocking phpunit


【解决方案1】:

这不是expects 所做的——它所做的只是告诉模拟在调用该函数时要返回什么。这不是断言。

如果你想断言某个方法被调用,我会查看https://github.com/phpspec/prophecy#spies

或者,您可以使用 returnCallback 保存调用的参数,然后将其与您知道的参数进行比较,例如:

$params = [];
$permutator->expects($this->any())
->method('get_permutation')
->will($this->returnCallback(
    function($param) use (&$params){
        $params[] = $param);
    }
));

doTheThing();

$this->assertEquals(
  array(1,2),
  $params
);

【讨论】:

  • 我明白你的意思。虽然, "->expects($this->exactly(2))->..." 正是这样做的。但是,我猜我对“->expects(at(...))”的期望并不完全正确。我设法实现了我在 onConsecutiveCalls 上尝试做的事情。
  • expects() 设置在测试结束时验证的期望。期望就是断言。
猜你喜欢
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 2014-12-08
  • 1970-01-01
  • 2020-03-01
  • 2012-04-23
  • 1970-01-01
  • 2012-05-08
相关资源
最近更新 更多