问题描述
|
有谁知道是否有一个“ 0”或类似的东西可以测试被测代码中是否抛出了异常?
解决方法
<?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文档
PHPUnit作者文章提供了有关测试异常最佳实践的详细说明。
,您还可以使用docblock批注:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
对于PHP 5.5+(尤其是带有命名空间的代码),我现在更喜欢使用::class
,如果您在PHP 5.5+上运行,则可以使用::class
解析度来获取带有expectException
/setExpectedException
的类的名称。这提供了几个好处:
该名称将带有其名称空间(如果有)完全限定。
它解析为“ 7”,因此可以与任何版本的PHPUnit一起使用。
您将在IDE中获得代码完成功能。
如果您键入错误的类名,PHP编译器将发出错误。
例:
namespace \\My\\Cool\\Package;
class AuthTest extends \\PHPUnit_Framework_TestCase
{
public function testLoginFailsForWrongPassword()
{
$this->expectException(WrongPasswordException::class);
Auth::login(\'Bob\',\'wrong\');
}
}
PHP编译
WrongPasswordException::class
进入
\"\\My\\Cool\\Package\\WrongPasswordException\"
没有PHPUnit是更明智的选择。
注意:PHPUnit 5.2引入了ѭ5来代替setExpectedException
。
,下面的代码将测试异常消息和异常代码。
重要说明:如果也未引发预期的异常,它将失败。
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());
}
,您可以使用assertException扩展在一个测试执行期间声明一个以上的异常。
将方法插入TestCase并使用:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test,\'InvalidArgumentException\',100,\'expected message\' );
}
我还为喜欢精美代码的爱好者们赋予了一个特质。
,一种替代方法可以是以下方法:
$this->expectException(\\InvalidArgumentException::class);
$this->expectExceptionMessage(\'Expected Exception Message\');
请确保您的测试课程范围为\\PHPUnit_Framework_TestCase
。
,PHPUnit的“ 5”方法非常不便,因为每个测试方法只能测试一个异常。
我已经使这个辅助函数断言某些函数抛出异常:
/**
* 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\');
});
}
,public function testException() {
try {
$this->methodThatThrowsException();
$this->fail(\"Expected Exception has not been raised.\");
} catch (Exception $ex) {
$this->assertEquals($ex->getMessage(),\"Exception message\");
}
}
,综合解决方案
PHPUnit \当前用于例外测试的“最佳实践”似乎..缺乏光泽(文档)。
因为我想要的不仅仅是当前的“ 5”实现,所以我在测试用例中使用了一个特质。大约只有50行代码。
支持每个测试多个异常
支持引发异常后调用的断言
稳健而清晰的用法示例
标准assert
语法
支持断言,而不仅仅是消息,代码和类
支持反断言,assertNotThrows
支持PHP 7Throwable
错误
图书馆
我向Github和packagist发布了ѭ25特征,以便可以在作曲家中安装它。
简单的例子
只是为了说明语法背后的精神:
<?php
// Using simple callback
$this->assertThrows(MyException::class,[$obj,\'doSomethingBad\']);
// Using anonymous function
$this->assertThrows(MyException::class,function() use ($obj) {
$obj->doSomethingBad();
});
挺整洁的?
完整用法示例
请参阅下面的更全面的用法示例:
<?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();
});
}
}
?>
,您可以执行以下所有异常断言。请注意,所有这些都是可选的。
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!\');
}
}
文档可以在这里找到。
,/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
小心\"/**\"
,注意双“ *”。只写\“ ** \”(星号)将使您的代码失败。
还要确保您使用的是最新版本的phpUnit。在phpunit的某些早期版本中,@expectedException不支持异常。我有4.0,但对我来说不起作用,我必须更新到5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer才能使用composer进行更新。
,对于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());
}
,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是一个了不起的库,但是这一点有点令人沮丧。这就是为什么我们可以使用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/\');
如果我们在匿名函数中键入的代码未引发异常,则将引发异常。
如果我们在匿名函数中键入的代码引发异常,但其消息与预期的正则表达式不匹配,则也会引发异常。