답변:
<?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 작성자 기사 는 예외 모범 사례 테스트에 대한 자세한 설명을 제공합니다.
$this->setExpectedException('\My\Name\Space\MyCustomException');
expectException()
. 어떤 사람들에게는 분명했을지 모르지만 그것은 나에게 큰 어려움 이었습니다.
PHPUnit 9가 출시 될 때까지 docblock 주석을 사용할 수도 있습니다 :
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
PHP 5.5 이상 (특히 네임 스페이스 코드)의 경우 이제는 ::class
IncorrectPasswordException
메시지가 동일하다는 "Wrong password for bob@me.com"
것은 부수적입니다. 테스트 작성에 적은 시간을 투자하고 간단한 테스트가 얼마나 중요한지 알아보기 시작하십시오.
당신이 PHP 5.5 이상에서 실행하는 경우 사용할 수있는 ::class
해상도를 가지는 클래스의 이름을 얻기 위해 expectException
/을setExpectedException
. 이것은 몇 가지 이점을 제공합니다.
string
모든 버전의 PHPUnit에서 작동하도록 해결합니다 .예:
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는를
expectException
대신하여 도입 되었습니다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());
}
$this->fail()
적어도 현재는 생각하지 않는 방식으로 사용되지는 않습니다 (PHPUnit 3.6.11). 그것은 예외 그 자체로 작용합니다. 귀하의 예제를 사용하는 경우 $this->fail("Expected exception not thrown")
라고하며, 다음 catch
블록은 트리거되고 $e->getMessage()
있다 "예외가 발생하지 예상" .
fail
아마도 try 내부가 아닌 catch 블록 뒤에 속합니다 .
fail
이 try
차단 되어서는 안되므로 하향 투표를 해야합니다 . 자체적으로 catch
블록이 잘못된 결과를 생성 하도록 트리거합니다 .
catch(Exception $e)
. 이 방법은 특정 예외를 잡으려고 할 때 매우 효과적입니다.try { throw new MySpecificException; $this->fail('MySpecificException not thrown'); } catch(MySpecificException $e){}
assertException 확장을 사용할 수 있습니다 을 한 번의 테스트 실행 중에 둘 이상의 예외를 선언 .
TestCase에 메소드를 삽입하고 다음을 사용하십시오.
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
나는 또한 좋은 코드를 좋아하는 사람들을 위해 특성 을 만들었다 ..
assertException
정의되어 있지 않습니다. 또한 PHPUnit 매뉴얼에서 찾을 수 없습니다.
asertException
메소드는 원래 PHPUnit의 일부가 아닙니다. 위의 게시물에 링크 된PHPUnit_Framework_TestCase
클래스 를 상속하고 메소드를 수동으로 추가 해야합니다 . 그런 다음 테스트 사례는이 상속 된 클래스를 상속합니다.
다른 방법은 다음과 같습니다.
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
당신의 테스트 클래스 범위를 확인하십시오 \PHPUnit_Framework_TestCase
.
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, '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');
});
}
예외 테스트를위한 PHPUnit의 현재 " 모범 사례 "는 .. lackluster ( docs )입니다.
현재 구현 보다 더 많은 것을 원했기 때문에 expectException
테스트 사례에 사용할 특성을 만들었습니다. 그것은 단지의 코드 ~ 50 라인 .
assert
구문assertNotThrows
Throwable
오류 지원나는 AssertThrows
특성을 Github과 packagist에 게시하여 작곡가와 함께 설치할 수 있습니다.
구문의 기본 개념을 설명하기 위해 :
<?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();
});
}
}
?>
public function testException() {
try {
$this->methodThatThrowsException();
$this->fail("Expected Exception has not been raised.");
} catch (Exception $ex) {
$this->assertEquals($ex->getMessage(), "Exception message");
}
}
assertEquals()
되어 assertEquals(mixed $expected, mixed $actual...)
그것이 있어야하므로, 귀하의 예에서와 같이 역$this->assertEquals("Exception message", $ex->getMessage());
여기 당신이 할 수있는 모든 예외 주장이 있습니다. 그들 모두는 선택 사항 입니다.
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);
}
에 대해 매우주의 "/**"
하여 이중 "*"를 확인하십시오. "**"(asterix) 만 작성하면 코드가 실패합니다. 또한 최신 버전의 phpUnit을 사용해야합니다. 이전 버전의 phpunit @expectedException 예외는 지원되지 않습니다. 나는 4.0을 가지고 있었고 그것은 나를 위해 작동하지 않았다, 나는 작곡가 로 업데이트하려면 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer 로 업데이트해야했다.
PHPUnit 5.7.27 및 PHP 5.6의 경우 한 번의 테스트로 여러 예외를 테스트하려면 예외 테스트를 강제 실행하는 것이 중요했습니다. 예외 처리 만 단독으로 사용하면 예외가 발생하지 않으면 예외 인스턴스가 상황 테스트를 건너 뜁니다.
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());
}
PhpUnit은 놀라운 라이브러리이지만이 점은 약간 실망 스럽습니다. 그렇기 때문에 예외 테스트에 도움이되는 매우 편리한 어설 션 방법이있는 turbotesting-php 오픈 소스 라이브러리를 사용할 수 있습니다. 여기에 있습니다.
그리고 그것을 사용하기 위해 우리는 단순히 다음을 수행합니다.
AssertUtils::throwsException(function(){
// Some code that must throw an exception here
}, '/expected error message/');
익명 함수에 입력 한 코드에서 예외가 발생하지 않으면 예외가 발생합니다.
익명 함수에 입력 한 코드에서 예외가 발생하지만 해당 메시지가 예상 정규 표현식과 일치하지 않으면 예외도 발생합니다.