Weiß jemand, ob es eine assert
oder eine ähnliche gibt, die testen kann, ob im getesteten Code eine Ausnahme ausgelöst wurde?
Weiß jemand, ob es eine assert
oder eine ähnliche gibt, die testen kann, ob im getesteten Code eine Ausnahme ausgelöst wurde?
Antworten:
<?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);
}
}
erwartete EXception () PHPUnit-Dokumentation
Der Artikel des PHPUnit-Autors enthält detaillierte Erläuterungen zum Testen der Best Practices für Ausnahmen.
$this->setExpectedException('\My\Name\Space\MyCustomException');
setExpectedException
Methode veraltet und wird durch die expectException
ersetzt. :)
expectException()
. Während es für manche offensichtlich gewesen sein mag, war es ein Gotcha für mich.
Sie können auch eine Docblock-Annotation verwenden, bis PHPUnit 9 veröffentlicht wird:
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
...
}
}
Für PHP 5.5+ (insbesondere mit Namespace-Code) bevorzuge ich jetzt die Verwendung ::class
IncorrectPasswordException
sollte ausreichen - dass die Nachricht gleich "Wrong password for bob@me.com"
ist, ist ergänzend. Fügen Sie hinzu, dass Sie so wenig Zeit wie möglich mit dem Schreiben von Tests verbringen möchten, und Sie beginnen zu sehen, wie wichtig einfache Tests werden.
Wenn Sie mit PHP 5.5+ arbeiten, können Sie die ::class
Auflösung verwenden , um den Namen der Klasse mit expectException
/setExpectedException
abzurufen . Dies bietet mehrere Vorteile:
string
sodass 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 klüger ist.
Hinweis : PHPUnit 5.2 wurde
expectException
als Ersatz für eingeführtsetExpectedException
.
Der folgende Code testet die Ausnahmemeldung und den Ausnahmecode.
Wichtig: Es schlägt fehl, wenn die erwartete Ausnahme nicht ebenfalls ausgelöst 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());
}
$this->fail()
soll nicht so verwendet werden, glaube ich nicht, zumindest momentan nicht (PHPUnit 3.6.11); es fungiert selbst als Ausnahme. Mit Ihrem Beispiel, wenn $this->fail("Expected exception not thrown")
aufgerufen wird, dann wird der catch
Block wird ausgelöst und $e->getMessage()
wird „Erwartet keine Ausnahme ausgelöst“ .
fail
gehört wahrscheinlich nach dem catch-Block, nicht innerhalb des Try.
fail
nicht im try
Block sein sollte. Es löst an sich den catch
Block aus, der falsche Ergebnisse erzeugt.
catch(Exception $e)
. Diese Methode funktioniert ganz gut für mich, wenn ich versuche, bestimmte Ausnahmen zu fangen:try { throw new MySpecificException; $this->fail('MySpecificException not thrown'); } catch(MySpecificException $e){}
Mit der Erweiterung assertException können Sie während einer Testausführung mehr als eine Ausnahme aktivieren .
Fügen Sie die Methode in Ihren TestCase 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 ein Merkmal für Liebhaber von nettem Code gemacht.
assertException
ist nicht definiert. Ich kann es auch nicht im PHPUnit-Handbuch finden.
asertException
Methode ist nicht Teil der ursprünglichen PHPUnit. Sie müssen die PHPUnit_Framework_TestCase
Klasse erben und die im obigen Beitrag verknüpfte Methode manuell hinzufügen . Ihre Testfälle erben dann diese geerbte Klasse.
Ein alternativer Weg kann der folgende sein:
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected Exception Message');
Bitte stellen Sie sicher, dass Ihre Testklasse erweitert ist \PHPUnit_Framework_TestCase
.
Die PHPUnit- expectException
Methode ist sehr unpraktisch, da nur eine Ausnahme pro Testmethode getestet werden kann.
Ich habe diese Hilfsfunktion erstellt, um zu behaupten, dass eine Funktion eine Ausnahme auslöst:
/**
* 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 folgendermaßen auf:
public function testSomething() {
$this->assertException(\PDOException::class, function() {
new \PDO('bad:param');
});
$this->assertException(\PDOException::class, function() {
new \PDO('foo:bar');
});
}
Die aktuellen " Best Practices " von PHPUnit für Ausnahmetests scheinen .. glanzlos ( docs ).
Da ich mehr als die aktuelle expectException
Implementierung wollte, habe ich eine Eigenschaft für meine Testfälle erstellt. Es sind nur ~ 50 Codezeilen .
assert
SyntaxassertNotThrows
Throwable
FehlerIch habe das AssertThrows
Merkmal für Github und Packagist veröffentlicht, damit es mit 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?
Im Folgenden finden Sie ein umfassenderes 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();
});
}
}
?>
public function testException() {
try {
$this->methodThatThrowsException();
$this->fail("Expected Exception has not been raised.");
} catch (Exception $ex) {
$this->assertEquals($ex->getMessage(), "Exception message");
}
}
assertEquals()
ist assertEquals(mixed $expected, mixed $actual...)
, umgekehrt wie in Ihrem Beispiel, so sollte es sein$this->assertEquals("Exception message", $ex->getMessage());
Hier finden Sie alle Ausnahmen, 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 "/**"
, beachten Sie das doppelte "*". Wenn Sie nur "**" (Sternchen) schreiben, schlägt Ihr Code fehl. Stellen Sie außerdem sicher, dass Sie die letzte Version von phpUnit verwenden. In einigen früheren Versionen von phpunit @expectedException wird Exception nicht unterstützt. Ich hatte 4.0 und es funktionierte nicht für mich. Ich musste auf 5.5 https://coderwall.com/p/mklvdw/install-phpunit-with-composer aktualisieren, um mit Composer zu aktualisieren.
Für PHPUnit 5.7.27 und PHP 5.6 und um mehrere Ausnahmen in einem Test zu testen, war es wichtig, den Ausnahmetest zu erzwingen. Wenn Sie nur die Ausnahmebehandlung verwenden, um die Instanz der Ausnahme zu aktivieren, wird das Testen der Situation übersprungen, 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
}
}
PhpUnit ist eine erstaunliche Bibliothek, aber dieser spezielle Punkt ist ein bisschen frustrierend. Aus diesem Grund können wir die OpenSource-Bibliothek turbotesting-php verwenden, die über eine sehr praktische Assertionsmethode verfügt, mit der wir Ausnahmen testen können. Es ist hier zu finden:
Und um es zu verwenden, würden wir einfach Folgendes tun:
AssertUtils::throwsException(function(){
// Some code that must throw an exception here
}, '/expected error message/');
Wenn der Code, den wir in die anonyme Funktion eingeben, keine Ausnahme auslöst, wird eine Ausnahme ausgelöst.
Wenn der Code, den wir in die anonyme Funktion eingeben, eine Ausnahme auslöst, die Nachricht jedoch nicht mit dem erwarteten regulären Ausdruck übereinstimmt, wird auch eine Ausnahme ausgelöst.