有人知道是否有断言或类似的东西可以测试被测试的代码中是否抛出了异常吗?
当前回答
全面的解决方案
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();
});
}
}
?>
其他回答
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
注意“/**”,注意两个“*”。只写“**”(星号)将使代码失败。 同时确保你使用的是phpUnit的最新版本。在phpunit的一些早期版本中,不支持@expectedException异常。我有4.0,它不适合我,我必须更新到5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer更新与作曲家。
你也可以在PHPUnit 9发布之前使用文档块注释:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
对于PHP 5.5+(特别是带有命名空间的代码),我现在更喜欢使用::class
<?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 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());
}
以下是您可以执行的所有异常断言。注意,它们都是可选的。
class ExceptionTest extends PHPUnit_Framework_TestCase
{
public function testException()
{
// make your exception assertions
$this->expectException(InvalidArgumentException::class);
// if you use namespaces:
// $this->expectException('\Namespace\MyException');
$this->expectExceptionMessage('message');
$this->expectExceptionMessageRegExp('/essage$/');
$this->expectExceptionCode(123);
// code that throws an exception
throw new InvalidArgumentException('message', 123);
}
public function testAnotherException()
{
// repeat as needed
$this->expectException(Exception::class);
throw new Exception('Oh no!');
}
}
文档可以在这里找到。
推荐文章
- 如何实现一个好的脏话过滤器?
- PHP中的三个点(…)是什么意思?
- Guzzlehttp -如何从guzzle6得到响应的正文?
- 移动一个文件到服务器上的另一个文件夹
- Laravel中使用雄辩的ORM进行批量插入
- PHP 5.4调用时引用传递-容易修复可用吗?
- 格式化字节到千字节,兆字节,千兆字节
- 如何在PHP中获得变量名作为字符串?
- 用“+”(数组联合运算符)合并两个数组如何工作?
- 为什么不使用异常作为常规的控制流呢?
- Laravel PHP命令未找到
- 如何修复从源代码安装PHP时未发现xml2-config的错误?
- 在PHP中对动态变量名使用大括号
- 如何从对象数组中通过对象属性找到条目?
- 如何从关联数组中删除键及其值?