eth*_*ros 25 php phpunit unit-testing
使用PHPUnit测试异常时,要求每个语句或断言必须抛出异常才能使测试通过的最佳方法是什么?
我基本上想做这样的事情:
public function testExceptions()
{
$this->setExpectedException('Exception');
foo(-1); //throws exception
foo(1); //does not throw exception
}
//Test will fail because foo(1) did not throw an exception
Run Code Online (Sandbox Code Playgroud)
我想出了以下内容,它完成了这项工作,但IMO非常难看.
public function testExceptions()
{
try {
foo(-1);
} catch (Exception $e) {
$hit = true;
}
if (!isset($hit))
$this->fail('No exception thrown');
unset($hit);
try {
foo(1);
} catch (Exception $e) {
$hit = true;
}
if (!isset($hit))
$this->fail('No exception thrown');
unset($hit);
}
Run Code Online (Sandbox Code Playgroud)
Nic*_*ini 23
我认为这是单元测试中非常常见的情况.我在这种情况下使用的方法是使用phpunit dataProviders.一切都按预期工作,测试代码变得更加清晰简洁.
class MyTest extends PHPUnit\Framework\TestCase
{
public function badValues(): array
{
return [
[-1],
[1]
];
}
/**
* @dataProvider badValues
* @expectedException Exception
*/
public function testFoo($badValue): void
{
foo($badValue);
}
}
Run Code Online (Sandbox Code Playgroud)
Ali*_*man 20
由于异常是程序流程中的重大事件,因此在单个测试中测试多个事件是有问题的.
最简单的方法是简单地将它分成两个测试 - 第一个需要一个异常才能通过,第二个只是简单地运行,并且会失败它它会抛出一个.如果你想要的话,你可以在第二个中添加一些其他的测试(确认一个返回值),但是根据它的命名,我倾向于确保它仍然只做了一件必不可少的事情.
/**
* @expectedException Exception
*/
public function testBadFooThrowsException()
{
// optional, can also do it from the '@expectedException x'
//$this->setExpectedException('Exception');
foo(-1); //throws exception -- good.
}
public function testFooDoesNotThrowException()
{
foo(1); //does not throw exception
}
Run Code Online (Sandbox Code Playgroud)
稍微清洁的代码(但我仍然建议拆分你的测试:
try {
foo(-1);
$this->fail('No exception thrown');
} catch (Exception $e) {}
Run Code Online (Sandbox Code Playgroud)