Weiß jemand, ob es eine assert
oder etwas Ähnliches gibt, mit dem getestet werden kann, ob im getesteten Code eine Ausnahme ausgelöst wurde?
<?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-Dokumentation
PHPUnit-Artikel des Autors enthält detaillierte Erklärungen zu bewährten Vorgehensweisen für das Testen von Ausnahmen.
Wenn Sie mit PHP 5.5+ arbeiten, können Sie ::class
resolution verwenden, um den Namen der Klasse mit expectException
setExpectedException
zu erhalten. Dies bietet mehrere Vorteile:
string
auf, so dass es mit jeder Version von PHPUnit funktioniert.Beispiel:
namespace \My\Cool\Package;
class AuthTest extends \PHPUnit_Framework_TestCase
{
public function testLoginFailsForWrongPassword()
{
$this->expectException(WrongPasswordException::class);
Auth::login('Bob', 'wrong');
}
}
PHP kompiliert
WrongPasswordException::class
in
"\My\Cool\Package\WrongPasswordException"
ohne dass PHPUnit der klügere ist.
_/Note: PHPUnit 5.2 hat
expectException
als Ersatz fürsetExpectedException
eingeführt.
Der folgende Code testet die Ausnahmemeldung und den Ausnahmecode.
Wichtig: Es schlägt fehl, wenn die erwartete Ausnahme nicht ebenfalls geworfen wird.
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());
}
Sie können assertException extension verwenden, um während einer Testausführung mehrere Ausnahmen geltend zu machen.
Fügen Sie die Methode in Ihr Testfeld ein und verwenden Sie:
public function testSomething()
{
$test = function() {
// some code that has to throw an exception
};
$this->assertException( $test, 'InvalidArgumentException', 100, 'expected message' );
}
Ich habe auch eine Eigenschaft für Liebhaber von Nice-Code gemacht ..
Ein alternativer Weg kann der folgende sein:
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
Stellen Sie sicher, dass Ihre Testklasse \PHPUnit_Framework_TestCase
reicht.
public function testException() {
try {
$this->methodThatThrowsException();
$this->fail("Expected Exception has not been raised.");
} catch (Exception $ex) {
$this->assertEquals($ex->getMessage(), "Exception message");
}
}
PHPUnits aktuelles " Best Practices " für Ausnahmetests scheinen .. glanzlos ( docs ).
Da ich stimme überhaupt nicht zu mit der aktuellen expectException
-Implementierung, habe ich eine Eigenschaft für meine Testfälle erstellt. Es ist nur 50 Zeilen .
assert
SyntaxassertNotThrows
Ich habe das Merkmal AssertThrows
für Github und packagist veröffentlicht, damit es mit dem Composer installiert werden kann.
Nur um den Geist hinter der Syntax zu veranschaulichen:
<?php
// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);
// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
$obj->doSomethingBad();
});
Ziemlich ordentlich?
Nachfolgend finden Sie ein ausführlicheres Anwendungsbeispiel:
<?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();
});
}
}
?>
Die Methode PHPUnit expectException
ist sehr unpraktisch, da nur eine Ausnahme pro Testmethode getestet werden kann.
Ich habe diese Hilfsfunktion erstellt, um zu bestätigen, dass einige Funktionen eine Ausnahme auslösen:
/**
* 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');
}
Fügen Sie es Ihrer Testklasse hinzu und rufen Sie diesen Weg auf:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
Hier sind alle Ausnahmebestimmungen, die Sie ausführen können. Beachten Sie, dass alle optional sind.
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!');
}
}
Dokumentation finden Sie hier .
/**
* @expectedException Exception
* @expectedExceptionMessage Amount has to be bigger then 0!
*/
public function testDepositNegative()
{
$this->account->deposit(-7);
}
Seien Sie sehr vorsichtig bei "/**"
, beachten Sie das doppelte "*". Wenn Sie nur "**" (Asterix) schreiben, wird Ihr Code fehlschlagen. Stellen Sie außerdem sicher, dass Sie die letzte Version von phpUnit verwenden. In einigen früheren Versionen von phpunit @expectedException wird keine Ausnahme unterstützt. Ich hatte 4.0 und es funktionierte nicht für mich, ich musste ein Update auf 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer durchführen, um mit dem Composer zu aktualisieren.
Für PHPUnit 5.7.27 und PHP 5.6 und zum Testen mehrerer Ausnahmen in einem Test war es wichtig, den Ausnahmetest zu erzwingen. Die alleinige Verwendung der Ausnahmebehandlung zum Bestätigen der Instanz von Exception überspringt das Testen der Situation, wenn keine Ausnahme auftritt.
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>; }
}
hier ist der Test
class FunctionTest extends \PHPUnit_Framework_TestCase{
public function testException(){
$this->setExpectedException(<YOUR_EXCEPTION>::class);
yourfunction(1,2);//add vars that cause the exception
}
}