php PHPUnit 断言抛出异常?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5683592/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 22:11:50  来源:igfitidea点击:

PHPUnit assert that an exception was thrown?

phpexceptionphpunitassert

提问by Felipe Almeida

Does anyone know whether there is an assertor something like that which can test whether an exception was thrown in the code being tested?

有谁知道是否有assert类似的东西可以测试正在测试的代码中是否抛出异常?

回答by Frank Farmer

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

expectException() PHPUnit documentation

expectException() PHPUnit 文档

PHPUnit author articleprovides detailed explanation on testing exceptions best practices.

PHPUnit 作者文章提供了有关测试异常最佳实践的详细说明。

回答by David Harkness

You can also use a docblock annotationuntil PHPUnit 9 is released:

在 PHPUnit 9 发布之前,您还可以使用docblock 注释

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

For PHP 5.5+ (especially with namespaced code), I now prefer using ::class

对于 PHP 5.5+(尤其是命名空间代码),我现在更喜欢使用 ::class

回答by David Harkness

If you're running on PHP 5.5+, you can use ::classresolutionto obtain the name of the class with expectException/setExpectedException. This provides several benefits:

如果您在 PHP 5.5+ 上运行,您可以使用::class解析来获取带有expectException/setExpectedException的类的名称。这提供了几个好处:

  • The name will be fully-qualified with its namespace (if any).
  • It resolves to a stringso it will work with any version of PHPUnit.
  • You get code-completion in your IDE.
  • The PHP compiler will emit an error if you mistype the class name.
  • 该名称将以其命名空间(如果有)完全限定。
  • 它解析为 a,string因此它适用于任何版本的 PHPUnit。
  • 您可以在 IDE 中完成代码。
  • 如果您输入错误的类名,PHP 编译器将发出错误消息。

Example:

例子:

namespace \My\Cool\Package;

class AuthTest extends \PHPUnit_Framework_TestCase
{
    public function testLoginFailsForWrongPassword()
    {
        $this->expectException(WrongPasswordException::class);
        Auth::login('Bob', 'wrong');
    }
}

PHP compiles

PHP 编译

WrongPasswordException::class

into

进入

"\My\Cool\Package\WrongPasswordException"

without PHPUnit being the wiser.

没有 PHPUnit 是更明智的。

Note: PHPUnit 5.2 introducedexpectExceptionas a replacement for setExpectedException.

注意PHPUnit 5.2expectException作为setExpectedException.

回答by Farid Movsumov

Code below will test exception message and exception code.

下面的代码将测试异常消息和异常代码。

Important:It will fail if expected exception not thrown too.

重要提示:如果未抛出预期的异常,它将失败。

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

回答by hejdav

You can use assertException extensionto assert more than one exception during one test execution.

您可以使用assertException 扩展在一次测试执行期间断言多个异常。

Insert method into your TestCase and use:

将方法插入您的测试用例并使用:

public function testSomething()
{
    $test = function() {
        // some code that has to throw an exception
    };
    $this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}

I also made a traitfor lovers of nice code..

我还为喜欢漂亮代码的人创造了一个特征

回答by Antonis Charalambous

An alternative way can be the following:

另一种方法可以是以下:

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

Please ensure that your test class extents \PHPUnit_Framework_TestCase.

请确保您的测试类范围\PHPUnit_Framework_TestCase

回答by Finesse

The PHPUnit expectExceptionmethod is very inconvenient because it allows to test only one exception per a test method.

PHPUnitexpectException方法非常不方便,因为它允许每个测试方法只测试一个异常。

I've made this helper function to assert that some function throws an exception:

我已经制作了这个辅助函数来断言某些函数抛出异常:

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

Add it to your test class and call this way:

将它添加到您的测试类并以这种方式调用:

public function testSomething() {
    $this->assertException(\PDOException::class, function() {
        new \PDO('bad:param');
    });
    $this->assertException(\PDOException::class, function() {
        new \PDO('foo:bar');
    });
}

回答by jchook

Comprehensive Solution

综合解决方案

PHPUnit's current "best practices" for exception testing seem.. lackluster (docs).

PHPUnit 当前用于异常测试的“最佳实践”似乎……乏善可陈(文档)。

Since I wanted morethan the current expectExceptionimplementation, I made a trait to use on my test cases. It's only ~50 lines of code.

因为我想要的不仅仅是当前的expectException实现,所以我在我的测试用例中使用了一个 trait。它只有约 50 行代码

  • Supports multiple exceptions per test
  • Supports assertions called after the exception is thrown
  • Robust and clear usage examples
  • Standard assertsyntax
  • Supports assertions for more than just message, code, and class
  • Supports inverse assertion, assertNotThrows
  • Supports PHP 7 Throwableerrors
  • 每个测试支持多个异常
  • 支持抛出异常后调用断言
  • 强大而清晰的使用示例
  • 标准assert语法
  • 支持的断言不仅仅是消息、代码和类
  • 支持反向断言, assertNotThrows
  • 支持 PHP 7Throwable错误

Library

图书馆

I published the AssertThrowstrait to Github and packagistso it can be installed with composer.

我将AssertThrows特征发布到 Github 和packagist,以便它可以与作曲家一起安装。

Simple Example

简单示例

Just to illustrate the spirit behind the syntax:

只是为了说明语法背后的精神:

<?php

// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);

// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
    $obj->doSomethingBad();
});

Pretty neat?

漂亮整齐?



Full Usage Example

完整使用示例

Please see below for a more comprehensive usage example:

请参阅下面的更全面的使用示例:

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

?>

回答by ab_wanyama

public function testException() {
    try {
        $this->methodThatThrowsException();
        $this->fail("Expected Exception has not been raised.");
    } catch (Exception $ex) {
        $this->assertEquals($ex->getMessage(), "Exception message");
    }

}

回答by Westy92

Here's all the exception assertions you can do. Note that all of them are optional.

这是您可以执行的所有异常断言。请注意,所有这些都是可选的

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

Documentation can be found here.

文档可以在这里找到。