关于php:PHPUnit断言抛出异常?

PHPUnit assert that an exception was thrown?

有人知道是否有一个assert或者类似的东西可以测试在被测试的代码中是否抛出了异常?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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 author article provides detailed explanation on testing excepting exceptions best practices.


你还可以使用码头注释:

ZZU1

对于PHP 5.5+(特别是名称代码),我现在偏爱使用::class


如果你在PHP 5.5+上跑步,你可以使用::class决议,用expectException〔3〕填写班级名称。This provides several benefits:

  • The name will be fully-qualified with its namespace(if any).
  • 因此,它将与任何版本的Phpunit合作。
  • 你有自己的代码
  • 编译器会输出错误,如果您输入了编译器的名称。

Example:

1
2
3
4
5
6
7
8
9
10
namespace \My\Cool\Package;

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

PHP compiles

1
WrongPasswordException::class

进入

1
"\My\Cool\Package\WrongPasswordException"

没有弗普兰是维泽尔。

Note: PHPUnit 5.2 introduced expectException as a replacement for setExpectedException.


下面的代码将测试例外信息和例外代码。

重要的是,如果预期的例外情况不会太快就失败了。

1
2
3
4
5
6
7
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());
}


在一次执行测试中,您可以使用伺服接收扩展来伺服比一个例外更多。

Insert method into your testcase and use:

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

我还为尼斯的情人做了一个特质。


一种替代办法可以是:

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

请确保您的测试等级EDOCX1


1
2
3
4
5
6
7
8
9
public function testException() {
    try {
        $this->methodThatThrowsException();
        $this->fail("Expected Exception has not been raised.");
    } catch (Exception $ex) {
        $this->assertEquals($ex->getMessage(),"Exception message");
    }

}

综合溶液

Phpunt's current"Best practices"for excepting seem.Lackluster(Docs)。

自从我想要的比目前的expectException更多,我就在我的测试案例中做了一些使用。只有50条线的密码

  • 多载体例外测试
  • 支持断言在例外情况下被呼叫
  • 稳健清晰使用实例
  • 标准语法
  • 支持的争论,不仅仅是信息、代码和分类
  • 反馈介质断言
  • 支持PHP 7 EDOCX1&11

图书馆

我出版了吉普赛人和包装师的特征,所以可以用作曲家安装。

简单的例子

Just to implicate the spirit behind the syntax:

1
2
3
4
5
6
7
8
9
<?php

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

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

漂亮Neat?

全使用范例

Please see below for a more comprehensive use example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?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();
        });
    }
}

?>


该方法非常不合适,因为它允许对一种测试方法进行一次例外测试。

我做了这个帮助函数来确定某些函数有一个例外:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * 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');
}

将它添加到你的测试班,并呼叫这条路:

1
2
3
4
5
6
7
8
public function testSomething() {
    $this->assertException(\PDOException::class, function() {
        new \PDO('bad:param');
    });
    $this->assertException(\PDOException::class, function() {
        new \PDO('foo:bar');
    });
}


这是你能做的唯一的例外Note that all of them are optional.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class ExceptionTest extends PHPUnit_Framework_TestCase
{
    public function testException()
    {
        // make your exception assertions
        $this->expectException(InvalidArgumentException::class);
        // if you use namespaces:
        // $this->expectException('
amespace\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!');
    }
}

文件可以在这里找到。


1
2
3
4
5
6
7
8
/**
 * @expectedException Exception
 * @expectedExceptionMessage Amount has to be bigger then 0!
 */

public function testDepositNegative()
{
    $this->account->deposit(-7);
}

非常关心"/**",双重通知只写""&35&42;"(Asterix)will fail your code.还可以用phpunit的最后一个版本来保证你的安全。在某些早期版本的phpunit@expectedexception exception exception exception is not supported.我有4.0,但没有为我做任何工作,我不得不更新到5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer to update with composer.


对于Phpunit 5.7.27和PHP 5.6,以及对于在一次测试中测试多重除外情况,这对于强化除外测试十分重要。使用例外处理孤独来宣告例外处理程序将测试无例外情况下的情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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());

}