PHPUnit断言引发了异常?
<?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 article提供测试异常的最佳做法的详细说明。
+1不依赖魔术文档块 – SuperFamousGuy 2014-04-22 19:29:20
如果您使用命名空间,那么您需要输入完整的命名空间:'$ this-> setExpectedException('\ My \ Name \ Space \ MyCustomException');' – Alcalyn 2014-11-25 15:50:09
请注意,似乎没有一种明确期望没有例外的方法。您只需调用您的方法,如果抛出异常,测试将自动失败。 – 2015-06-23 14:53:11
你也可以使用一个docblock annotation:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
对于PHP 5.5+(特别是与命名空间中的代码),我现在更喜欢用下面::class
IMO,这是首选的方法。 – 2012-06-15 20:16:38
@MikePurcell,为什么? – 2013-05-23 07:04:00
@Falken教授:个人喜好。 Docblock注释保持测试方法的清洁,并且几个框架正在使用相同的做法; symfony 2,zf2。 – 2013-05-23 17:35:23
代码将测试异常消息和异常代码。
重要提示:如果预期的异常没有被抛出,它将会失败。
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());
}
'$ this-> fail()'并不意味着以这种方式使用,我不认为,至少目前不是(PHPUnit 3.6.11);它本身就是一种例外。使用你的例子,如果'$ this-> fail(“Expected exception not thrown”)被调用,那么'catch'模块被触发并且'$ e-> getMessage()'是_“期望的异常不被抛出_ 。 – ken 2014-04-16 21:33:51
@ken你可能是对的。对'失败'的调用可能属于* catch块之后,而不是在try中。 – 2014-04-22 20:41:57
我必须downvote,因为'fail'的调用不应该在'try'块中。它本身触发了“catch”块产生虚假结果。 – Twifty 2015-04-09 21:53:00
您可以使用assertException extension在一次测试执行期间声明多个异常。
方法插入到你的测试用例和使用:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException($test, 'InvalidArgumentException', 100, 'expected message');
}
我还做了好看的代码爱好者trait ...
您正在使用哪个PHPUnit?我正在使用PHPUnit 4.7.5,并且没有定义'assertException'。我也无法在PHPUnit手册中找到它。 – physicalattraction 2015-07-22 08:34:46
'asertException'方法不是原始PHPUnit的一部分。您必须手动继承'PHPUnit_Framework_TestCase'类并添加[在上面的帖子中链接的方法](https://gist.github.com/VladaHejda/8826707)。你的测试用例会继承这个继承的类。 – hejdav 2015-07-27 11:40:03
public function testException() {
try {
$this->methodThatThrowsException();
$this->fail("Expected Exception has not been raised.");
} catch (Exception $ex) {
$this->assertEquals($ex->getMessage(), "Exception message");
}
}
如果你在运行PHP 5.5+,您可以使用::class
resolution来获取expectException
/setExpectedException
的课程名称。这提供了几个好处:
- 该名称将完全限定其名称空间(如果有)。
- 它解析为
string
,因此它可以与任何版本的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 introduced
expectException
作为setExpectedException
的替代品。
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
要非常小心约"/**"
,注意双 “*”。只写“* *”(asterix)会使你的代码失败。 也请确保您使用的是phpUnit的最新版本。在phpunit的一些早期版本中,@expectedException异常不受支持。我有4.0,它不适合我,我不得不更新到5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer与作曲家更新。
的另一种方式可以是follwing:
$this->expectException(\Exception::class);
$this->expectExceptionMessage('Expected Exception Message');
请确保您的测试类范围\化PHPUnit_Framework_TestCase
这里的所有异常的断言,你可以做。请注意,它们全部是可选。
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!');
}
}
可以找到文档here。
PHPUnit expectException
方法非常不方便,因为它允许每个测试方法只测试一个异常。
我做了这个辅助函数来断言某些函数抛出一个异常:
/**
* 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);
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');
});
}
为这些问题的答案:什么测试函数中的多重断言,我只希望有一个抛出异常?我是否需要将它们分开并将其置于独立的测试功能中? – 2016-01-22 08:04:53