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
PHPUnit assert that an exception was thrown?
提问by Felipe Almeida
Does anyone know whether there is an assert
or 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
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 ::class
resolutionto 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
string
so 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 introduced
expectException
as a replacement forsetExpectedException
.
注意:PHPUnit 5.2
expectException
作为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 expectException
method 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 expectException
implementation, 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
assert
syntax - Supports assertions for more than just message, code, and class
- Supports inverse assertion,
assertNotThrows
- Supports PHP 7
Throwable
errors
- 每个测试支持多个异常
- 支持抛出异常后调用断言
- 强大而清晰的使用示例
- 标准
assert
语法 - 支持的断言不仅仅是消息、代码和类
- 支持反向断言,
assertNotThrows
- 支持 PHP 7
Throwable
错误
Library
图书馆
I published the AssertThrows
trait 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.
文档可以在这里找到。