PHPUnit:如何对同一方法的多次调用进行Mock
解决Mock方法多次调用返回不同值的问题
Hey there! Let's sort out how to get distinct return values from your mocked method when it's called multiple times. The problem with your current code is that $this->second() isn't a valid matcher in PHPUnit—luckily, we have several straightforward solutions for this scenario.
方法1:使用onConsecutiveCalls()(最简洁)
这是PHPUnit专门为连续调用返回不同值设计的方法,用法非常直观:
$mock = $this->getMockBuilder('Test') ->disableOriginalConstructor() ->setMethods(['testMethod']) ->getMock(); // 指定方法被调用2次,按顺序返回true、false $mock->expects($this->exactly(2)) ->method('testMethod') ->will($this->onConsecutiveCalls(true, false));
exactly(2)确保方法被调用恰好2次,onConsecutiveCalls()会按传入参数的顺序依次返回对应值。
方法2:使用at()匹配器(精准指定调用顺序)
如果你需要精准控制某一次调用的返回值,可以用at(),注意调用索引从0开始计数:
$mock = $this->getMockBuilder('Test') ->disableOriginalConstructor() ->setMethods(['testMethod']) ->getMock(); // 第1次调用(索引0)返回true $mock->expects($this->at(0)) ->method('testMethod') ->will($this->returnValue(true)); // 第2次调用(索引1)返回false $mock->expects($this->at(1)) ->method('testMethod') ->will($this->returnValue(false));
⚠️ 注意:at()是针对所有Mock方法的全局调用顺序,不是当前方法的单独调用顺序。如果你的测试里还有其他Mock方法被调用,索引会累加,这点要留意。
方法3:使用returnCallback()(灵活处理复杂逻辑)
如果需要更复杂的返回逻辑(比如根据参数、调用次数动态返回),可以用回调函数:
$mock = $this->getMockBuilder('Test') ->disableOriginalConstructor() ->setMethods(['testMethod']) ->getMock(); $callCount = 0; $mock->expects($this->exactly(2)) ->method('testMethod') ->will($this->returnCallback(function() use (&$callCount) { $callCount++; // 根据调用次数返回对应值,也可以扩展成根据参数判断的逻辑 return $callCount === 1 ? true : false; }));
总结
如果只是简单的连续调用返回固定顺序的值,方法1的onConsecutiveCalls()是最优选择,代码简洁且语义明确。
内容的提问来源于stack exchange,提问作者TIGER
相关产品推荐
相关产品推荐

