我想测试一个名为foo()
的方法会抛出异常。问题是我无法获得PHPUnit expectException()
来捕获异常。
foo()
看起来像这样:
public function foo()
{
$params = $this->readAndFormatConfig();
// exception actually gets thrown in this method
$this->method->throws->exception($params);
}
如果我手动捕获异常,它可以正常工作,如下所示:
public function testFoo()
{
$badConfig = new Config([]);
$driver = new bar($badConfig);
$exceptionThrown = false;
try {
$driver->foo();
} catch (Exception $e) {
$exceptionThrown = true;
}
$this->assertTrue($exceptionThrown);
}
如果我使用expectException捕获它,就像这样:
public function testFoo()
{
$badConfig = new Config([]);
$driver = new bar($badConfig);
$this->expectException(Exception::class);
$driver->foo();
}
测试失败,我得到了这个例外:
MyTestClass::testFoo Invalid argument supplied for foreach()
get_class($e)
的输出是PHPUnit_Framework_Error_Warning
让我感到惊讶,但解释了为什么第一次测试有效但第二次测试无效。
我想忽略警告并等到抛出真正的异常,或者获得原始警告,而不是PHPUnit_Framework_Error_Warning
。
我使用的是php 5.6.32和PHPUnit 5.7.15
答案 0 :(得分:0)
将以下内容添加到boostrap.php会将警告转换为异常。
function warningToException($errno, $errstr, $errfile, $errline)
{
throw new Exception($errstr . " on line " . $errline . " in file " . $errfile);
}
set_error_handler("warningToException", E_WARNING);
这允许以下测试通过。
public function testFoo()
{
$badConfig = new Config([]);
$driver = new bar($badConfig);
$this->expectException(Exception::class);
$driver->foo();
}
我认为更好的方法是在测试中期待PHPUnit_Framework_Error_Warning
,如ishegg建议的那样。
我最终实际做的是确保我传递给foreach的对象在进入循环之前是可遍历的。
public function foo()
{
if (is_array($x) || $x instanceof \Traversable) {
// do stuff
} else {
// return false;
}
}
我认为在这种情况下重构应用程序代码更有意义。我真正想要测试的是,如果应用程序配置错误,函数foo返回false,因此在我看来,正确处理错误配置似乎是正确的道路。
如果您出于某种原因偶然发现了这个问题,并且确实需要将警告转换为PHPUnit_Framework_Error_Warning
以外的异常类,这就是我的做法。
感谢ishegg指出我正确的方向。