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


当前回答

你也可以在PHPUnit 9发布之前使用文档块注释:

class ExceptionTest extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException InvalidArgumentException
     */
    public function testException()
    {
        ...
    }
}

对于PHP 5.5+(特别是带有命名空间的代码),我现在更喜欢使用::class

其他回答

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

以下是您可以执行的所有异常断言。注意,它们都是可选的。

class ExceptionTest extends PHPUnit_Framework_TestCase
{
    public function testException()
    {
        // make your exception assertions
        $this->expectException(InvalidArgumentException::class);
        // if you use namespaces:
        // $this->expectException('\Namespace\MyExceptio‌​n');
        $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!');
    }
}

文档可以在这里找到。

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 

   }

}

对于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());

}

PhpUnit是一个很棒的库,但这一点有点令人沮丧。这就是为什么我们可以使用turbotesting-php开源库,它有一个非常方便的断言方法来帮助我们测试异常。在这里可以找到:

https://github.com/edertone/TurboTesting/blob/master/TurboTesting-Php/src/main/php/utils/AssertUtils.php

要使用它,我们只需执行以下操作:

AssertUtils::throwsException(function(){

    // Some code that must throw an exception here

}, '/expected error message/');

如果我们在匿名函数中键入的代码没有抛出异常,则会抛出异常。

如果我们在匿名函数中键入的代码抛出异常,但其消息与预期的regexp不匹配,则也将抛出异常。