有人知道是否有断言或类似的东西可以测试被测试的代码中是否抛出了异常吗?
当前回答
下面的代码将测试异常消息和异常代码。
重要提示:如果没有抛出预期的异常,它将失败。
try{
$test->methodWhichWillThrowException();//if this method not throw exception it must be fail too.
$this->fail("Expected exception 1162011 not thrown");
}catch(MySpecificException $e){ //Not catching a generic Exception or the fail function is also catched
$this->assertEquals(1162011, $e->getCode());
$this->assertEquals("Exception Message", $e->getMessage());
}
其他回答
全面的解决方案
PHPUnit当前异常测试的“最佳实践”似乎…低迷(文档)。
由于我想要的不仅仅是当前的expectException实现,所以我在测试用例中使用了一个trait。它只有大约50行代码。
每个测试支持多个异常 支持异常抛出后调用的断言 健壮和清晰的使用示例 标准断言语法 不仅支持消息、代码和类的断言 支持反向断言,assertNotThrows 支持PHP 7可抛出错误
图书馆
我发布了AssertThrows trait到Github和packagist,这样它就可以与composer一起安装了。
简单的例子
只是为了说明语法背后的精神:
<?php
// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);
// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
很整洁的?
完整使用示例
请看下面一个更全面的使用示例:
<?php
declare(strict_types=1);
use Jchook\AssertThrows\AssertThrows;
use PHPUnit\Framework\TestCase;
// These are just for illustration
use MyNamespace\MyException;
use MyNamespace\MyObject;
final class MyTest extends TestCase
{
use AssertThrows; // <--- adds the assertThrows method
public function testMyObject()
{
$obj = new MyObject();
// Test a basic exception is thrown
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
// Test custom aspects of a custom extension class
$this->assertThrows(MyException::class,
function() use ($obj) {
$obj->doSomethingBad();
},
function($exception) {
$this->assertEquals('Expected value', $exception->getCustomThing());
$this->assertEquals(123, $exception->getCode());
}
);
// Test that a specific exception is NOT thrown
$this->assertNotThrows(MyException::class, function() use ($obj) {
$obj->doSomethingGood();
});
}
}
?>
您可以使用assertException扩展在一次测试执行期间断言多个异常。
插入方法到您的TestCase并使用:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
我还为喜欢漂亮代码的人做了一个trait ..
<?php
require_once 'PHPUnit/Framework.php';
class ExceptionTest extends PHPUnit_Framework_TestCase
{
public function testException()
{
$this->expectException(InvalidArgumentException::class);
// or for PHPUnit < 5.2
// $this->setExpectedException(InvalidArgumentException::class);
//...and then add your test code that generates the exception
exampleMethod($anInvalidArgument);
}
}
PHPUnit文档
PHPUnit作者文章提供了关于测试异常最佳实践的详细解释。
PHPUnit expectException方法非常不方便,因为它只允许每个测试方法测试一个异常。
我使用这个helper函数来断言某个函数抛出异常:
/**
* Asserts that the given callback throws the given exception.
*
* @param string $expectClass The name of the expected exception class
* @param callable $callback A callback which should throw the exception
*/
protected function assertException(string $expectClass, callable $callback)
{
try {
$callback();
} catch (\Throwable $exception) {
$this->assertInstanceOf($expectClass, $exception, 'An invalid exception was thrown');
return;
}
$this->fail('No exception was thrown');
}
将它添加到您的测试类中,并以这样的方式调用:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
对于PHPUnit 5.7.27和PHP 5.6,要在一个测试中测试多个异常,强制进行异常测试是很重要的。如果没有异常发生,则单独使用异常处理来断言exception实例将跳过对情况的测试。
public function testSomeFunction() {
$e=null;
$targetClassObj= new TargetClass();
try {
$targetClassObj->doSomething();
} catch ( \Exception $e ) {
}
$this->assertInstanceOf(\Exception::class,$e);
$this->assertEquals('Some message',$e->getMessage());
$e=null;
try {
$targetClassObj->doSomethingElse();
} catch ( Exception $e ) {
}
$this->assertInstanceOf(\Exception::class,$e);
$this->assertEquals('Another message',$e->getMessage());
}
推荐文章
- 如何实现一个好的脏话过滤器?
- PHP中的三个点(…)是什么意思?
- Guzzlehttp -如何从guzzle6得到响应的正文?
- 移动一个文件到服务器上的另一个文件夹
- Laravel中使用雄辩的ORM进行批量插入
- PHP 5.4调用时引用传递-容易修复可用吗?
- 格式化字节到千字节,兆字节,千兆字节
- 如何在PHP中获得变量名作为字符串?
- 用“+”(数组联合运算符)合并两个数组如何工作?
- 为什么不使用异常作为常规的控制流呢?
- Laravel PHP命令未找到
- 如何修复从源代码安装PHP时未发现xml2-config的错误?
- 在PHP中对动态变量名使用大括号
- 如何从对象数组中通过对象属性找到条目?
- 如何从关联数组中删除键及其值?