有人知道是否有断言或类似的东西可以测试被测试的代码中是否抛出了异常吗?


当前回答

你也可以在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作者文章提供了关于测试异常最佳实践的详细解释。

public function testException() {
    try {
        $this->methodThatThrowsException();
        $this->fail("Expected Exception has not been raised.");
    } catch (Exception $ex) {
        $this->assertEquals("Exception message", $ex->getMessage());
    }
    
}
function yourfunction($a,$z){
   if($a<$z){ throw new <YOUR_EXCEPTION>; }
}

下面是测试

class FunctionTest extends \PHPUnit_Framework_TestCase{

   public function testException(){

      $this->setExpectedException(<YOUR_EXCEPTION>::class);
      yourfunction(1,2);//add vars that cause the exception 

   }

}

另一种方法是:

$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');

请确保您的测试类扩展\PHPUnit_Framework_TestCase。

全面的解决方案

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();
        });
    }
}

?>