473 Stimmen

PHPUnit behaupten, dass eine Ausnahme ausgelöst wurde?

Weiß jemand, ob es eine assert oder etwas Ähnliches, das prüfen kann, ob im getesteten Code eine Ausnahme ausgelöst wurde?

37voto

Farid Movsumov Punkte 11508

Der folgende Code testet die Ausnahmemeldung und den Ausnahmecode.

Das ist wichtig: Er schlägt fehl, wenn die erwartete Ausnahme nicht auch 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());
}

25voto

hejdav Punkte 1067

Sie können verwenden assertException-Erweiterung um mehr als eine Ausnahme während einer Testausführung geltend zu machen.

Methode in Ihren TestCase einfügen und verwenden:

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 des schönen Codes..

21voto

Finesse Punkte 8132

Das PHPUnit expectException Methode ist sehr ungünstig, da sie nur eine Ausnahme pro Testmethode zulässt.

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 sie zu Ihrer Testklasse hinzu und rufen Sie sie so auf:

public function testSomething() {
    $this->assertException(\PDOException::class, function() {
        new \PDO('bad:param');
    });
    $this->assertException(\PDOException::class, function() {
        new \PDO('foo:bar');
    });
}

14voto

jchook Punkte 5914

Umfassende Lösung

PHPUnit's aktuelle " beste Praktiken " für Ausnahmetests scheinen glanzlos ( docs ).

Da ich mehr gesucht als die aktuelle expectException Implementierung habe ich einen Trait für meine Testfälle erstellt. Es ist nur ~50 Zeilen Code .

  • Unterstützt mehrere Ausnahmen pro Test
  • Unterstützt Assertions, die aufgerufen werden, nachdem die Ausnahme ausgelöst wurde
  • Robuste und klare Anwendungsbeispiele
  • Standard assert Syntax
  • Unterstützt Assertions für mehr als nur Nachricht, Code und Klasse
  • Unterstützt die inverse Behauptung, assertNotThrows
  • Unterstützt PHP 7 Throwable Fehler

Bibliothek

Ich habe die AssertThrows Eigenschaft auf Github und Verpacker damit es mit Composer installiert werden kann.

Einfaches Beispiel

Nur um den Sinn der Syntax zu verdeutlichen:

<?php

// Using simple callback
$this->assertThrows(MyException::class, [$obj, 'doSomethingBad']);

// Using anonymous function
$this->assertThrows(MyException::class, function() use ($obj) {
    $obj->doSomethingBad();
});

Ist das nicht toll?


Beispiel für die vollständige Verwendung

Ein ausführlicheres Beispiel für die Verwendung finden Sie weiter unten:

<?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();
        });
    }
}

?>

10voto

ab_wanyama Punkte 177
public function testException() {
    try {
        $this->methodThatThrowsException();
        $this->fail("Expected Exception has not been raised.");
    } catch (Exception $ex) {
        $this->assertEquals("Exception message", $ex->getMessage());
    }

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X