PHPUnit Mocked 方法导致异常

PHPUnit Mocked method causes an exception

我在 class

中有这个功能
public function doSomething()
{
    try {
        $result = functionCall();
        if ($result === true) {
            $this->doGoodResult('With Success Message');
        } else {
            $this->doBadResult('ERROR - unable to do something');
        }
    } catch (Exception $e) {
        $this->doBadResult('Did you divide by zero?');
    }
}

我正在尝试通过模拟额外功能来测试它

public function test_doSomthingWithBadResultGetsDoBadResultCalled()
{
    $ajc = $this->getMockBuilder('MyClass')
        ->setMethods(array('doBadResult'))
        ->setConstructorArgs(array('doSomething', array('input_var' => 0)))
        ->getMock();
    $ajc->expects($this->once())
        ->method('doBadResult')
        ->willReturn(null)
        ->with($this->contains('ERROR - unable to do something'));
    $ajc->doSomething();
}

问题是我从 PHPUnit

收到以下错误
MyClass::doBadResult('Did you divide by zero?') was not expected to be called more than once.

我不确定为什么,但看起来只有在这个模拟场景中才会执行 catch 语句。

谁能帮我弄清楚为什么会这样,尤其是如何设置它以使我的测试不会失败?

经过一些调试,我发现异常是 Invalid argument supplied for foreach(),经过一些挖掘,它在 $this->contains('ERROR...')

答案是$this->contains应该是$this->stringContains

为了防止你以后需要做更多的挖掘工作。您在代码中遇到的问题之一是您正在捕获基本异常类型。

} catch (Exception $e) {
    $this->doBadResult('Did you divide by zero?');
}

当 PHPUnit 中的断言失败时,将抛出 PHPUnit_Framework_AssertionFailedError 并被 PHPUnit 捕获。此错误扩展了基础 PHP 异常 class。因此,当调用模拟对象时,在您的 try 块中,它会检查所使用的参数。由于这些不正确,它会抛出您的 catch 语句获取的 PHPUnit_Framework_AssertionFailedError 。然后在您的 mock 上调用不希望被调用的方法。

因此,您的测试可能会错误地通过。因为失败的断言会被您的代码捕获并处理。您应该有一个您的 catch 正在寻找的特定异常,并且任何其他异常都会传递到适当的级别。