public function testException() {
try {
$this->methodThatThrowsException();
$this->fail("Expected Exception has not been raised.");
} catch (Exception $ex) {
$this->assertEquals($ex->getMessage(), "Exception message");
}
}
393
下面的代码将测试异常消息和异常代码 .
Important: 如果没有抛出预期的异常,它将失败 .
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());
}
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
<?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);
}
}
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
// Within your test case...
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
很简约?
完整用法示例
这是一个实际的TestCase类,它显示了一个更全面的用法示例:
<?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();
});
}
}
?>
/**
* 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');
});
}
4
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
12 回答
另一种方法可以是:
请确保您的测试类扩展
\PHPUnit_Framework_TestCase
.下面的代码将测试异常消息和异常代码 .
Important: 如果没有抛出预期的异常,它将失败 .
您可以使用assertException extension在一次测试执行期间声明多个异常 .
将方法插入TestCase并使用:
我也为好的代码爱好者做了一个trait ..
expectException() PHPUnit documentation
PHPUnit author article提供了有关测试异常最佳实践的详细说明 .
你也可以使用docblock annotation:
对于PHP 5.5(特别是使用命名空间代码),我现在更喜欢使用::class
如果您在PHP 5.5上运行,则可以使用::class resolution获取具有expectException/setExpectedException的类的名称 . 这提供了几个好处:
该名称将使用其命名空间(如果有)完全限定 .
它解析为
string
,因此它可以与任何版本的PHPUnit一起使用 .您可以在IDE中获得代码完成 .
如果您错误输入类名,PHP编译器将发出错误 .
例:
PHP编译
成
没有PHPUnit是更明智的 .
这是你可以做的所有异常断言 . 请注意,所有这些都是可选的 .
文档可以在here找到 .
PHPUnit目前用于异常测试的“best practices”是......乏善可陈 .
不支持每个测试的多个异常,或者抛出异常后调用的断言
文档缺乏健全或明确的例子
非标准且可能令人困惑的语法("expect" vs "assert")
仅支持消息,代码和类的断言
无反转,例如"expectNoException"
我为PHPUnit打开了一个Github issue,并立即被维护者解雇了 .
由于我强烈不同意当前的expectException实现,因此我在我的测试用例中使用了一个特性 .
图书馆
AssertThrows特性发布到Github和packagist,因此它可以与作曲家一起安装 .
简单示例
只是为了说明语法背后的精神:
很简约?
完整用法示例
这是一个实际的TestCase类,它显示了一个更全面的用法示例:
PHPUnit
expectException
方法非常不方便,因为它允许每个测试方法只测试一个异常 .我已经使这个辅助函数断言某些函数抛出异常:
将它添加到您的测试类并以这种方式调用:
关于
"/**"
要非常小心,注意双"*" . 只写"**"(asterix)会使代码失败 . 还要确保使用最新版本的phpUnit . 在某些早期版本的phpunit中,@ expectedException不支持异常 . 我有4.0,它不适合我,我不得不更新到5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer更新与作曲家 .对于PHPUnit 5.7.27和PHP 5.6以及在一次测试中测试多个异常,强制进行异常测试非常重要 . 如果没有异常发生,单独使用异常处理来断言Exception实例将跳过测试情况 .