Frage

Diese Frage ist spezifisch für mit PHPUnit.

PHPUnit wandelt automatisch PHP-Fehler zu Ausnahmen. Gibt es eine Möglichkeit, den Rückgabewert einer Methode zu testen, die ein PHP-Fehler (entweder eingebaut in Fehler oder Benutzer erzeugt Fehler über trigger_error )?

Beispiel-Code zu testen:

function load_file ($file)
{
    if (! file_exists($file)) {
        trigger_error("file {$file} does not exist", E_USER_WARNING);
        return false;
    }
    return file_get_contents($file);
}

Dies ist die Art von Test, den ich schreiben will:

public function testLoadFile ()
{
    $this->assertFalse(load_file('/some/non-existent/file'));
}

Das Problem, das ich habe ist, dass der ausgelöste Fehler meines Unit-Test (wie es sein soll) scheitern verursacht. Aber wenn ich versuche, es zu fangen, oder eine erwartete Ausnahme, dass jeder Code festgelegt, nachdem der Fehler ausgelöst wird nie ausgeführt, so habe ich keine Möglichkeit, den Rückgabewert der Methode zu testen.

Dieses Beispiel funktioniert nicht:

public function testLoadFile ()
{
    $this->setExpectedException('Exception');
    $result = load_file('/some/non-existent/file');

    // code after this point never gets executed

    $this->assertFalse($result);
}

Irgendwelche Ideen, wie ich das erreichen kann?

War es hilfreich?

Lösung

Es gibt keine Möglichkeit, dies innerhalb einer Einheit Test zu tun. Es ist möglich, wenn Sie den Rückgabewert testen zu brechen, und die Mitteilung in zwei verschiedene Tests.

Wie PHPUnit Fehlerhandler fängt PHP-Fehler dar und wandelt sie in Ausnahmen - die definitionsProgrammAusführung stoppt. Die Funktion, die Sie testen werden wieder überhaupt nicht. Sie können jedoch vorübergehend die Umwandlung von Fehlern in Ausnahmen deaktivieren, selbst zur Laufzeit.

Dies ist wahrscheinlich einfacher, mit einem Beispiel, so, hier ist es, was die beiden Tests sollen wie folgt aussehen:

public function testLoadFileTriggersErrorWhenFileNotFound()
{
    $this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
    $result = load_file('/some/non-existent/file');

}

public function testLoadFileRetunsFalseWhenFileNotFound()
{
    PHPUnit_Framework_Error_Warning::$enabled = FALSE;
    $result = load_file('/some/non-existent/file');

    $this->assertFalse($result);
}

Dies hat auch den zusätzlichen Bonus Ihrer Tests klarer, sauberer und selbstdokumentiere zu machen.

Re: Kommentar: Das ist eine große Frage, und ich hatte keine Ahnung, bis ich ein paar Tests lief. Es sieht aus, als ob es wird nicht die Standard / ursprünglichen Wert wiederherzustellen, zumindest von PHPUnit 3.3.17 (die aktuelle stabile Version jetzt).

Also, ich würde die oben tatsächlich ändern, wie so aussehen:

public function testLoadFileRetunsFalseWhenFileNotFound()
{
    $warningEnabledOrig = PHPUnit_Framework_Error_Warning::$enabled;
    PHPUnit_Framework_Error_Warning::$enabled = false;

    $result = load_file('/some/non-existent/file');

    $this->assertFalse($result);

    PHPUnit_Framework_Error_Warning::$enabled = $warningEnabledOrig;
}

Re: Zweite Bemerkung:

Das ist nicht ganz richtig. Ich bin auf PHPUnit Fehlerbehandlung suchen, und es funktioniert wie folgt:

  • Wenn es eine E_WARNING, Verwendung PHPUnit_Framework_Error_Warning als Ausnahmeklasse.
  • Wenn es ein E_NOTICE oder E_STRICT Fehler ist, verwenden Sie PHPUnit_Framework_Error_Notice
  • Else, verwenden PHPUnit_Framework_Error als Ausnahmeklasse.

Also, ja, Fehler der E_USER_* nicht in PHPUnit * _Warning eingeschaltet sind oder * _Notice Klasse, sind sie immer noch in eine generische PHPUnit_Framework_Error Ausnahme umgewandelt.

Weitere Gedanken

Während es genau abhängt, wie die Funktion verwendet wird, würde ich wahrscheinlich wechseln eine tatsächliche Ausnahme statt Auslösen eines Fehlers zu werfen, wenn es nach mir ginge. Ja, das würde den Ablauf des Verfahrens Logik ändern, und den Code, der die Methode verwendet ... jetzt die Ausführung stoppt nicht, wenn eine Datei nicht lesen kann. Aber das ist an Ihnen zu entscheiden, ob die angeforderte Datei nicht existiert, ist wirklich außergewöhnliche Verhalten. Ich neige dazu, Ausnahmen Art und Weise mehr als Fehler / Warnungen / Hinweise zu verwenden, da sie einfacher zu handhaben sind, zu testen und arbeiten in Ihre Anwendung fließen. Ich in der Regel die Hinweise für Dinge wie abgeschrieben Methodenaufrufe reservieren, etc.

Andere Tipps

eine phpunit.xml Konfigurationsdatei verwenden und die Benachrichtigung / Warnung / Fehler Ausnahme Konvertierung deaktivieren. Mehr Details im Handbuch . Es ist im Grunde so etwas wie folgt aus:

<phpunit convertErrorsToExceptions="false"
         convertNoticesToExceptions="false"
         convertWarningsToExceptions="false">
</phpunit>

Statt eines generischen "Exception" erwartet, was eine "PHPUnit_Framework_Error" erwartet?

So etwas wie dies tun könnte:

/**
 * @expectedException PHPUnit_Framework_Error
 */
public function testFailingInclude()
{
    include 'not_existing_file.php';
}

Which, nehme ich an, vielleicht auch wie folgt geschrieben werden:

public function testLoadFile ()
{
    $this->setExpectedException('PHPUnit_Framework_Error');
    $result = load_file('/some/non-existent/file');

    // code after this point never gets executed

    $this->assertFalse($result);
}

Weitere Informationen finden Sie unter Testen von PHP-Fehler
Vor allem heißt es (Zitat):

  

PHPUnit_Framework_Error_Notice und   PHPUnit_Framework_Error_Warning vertreten   PHP Hinweise und Warnungen sind.


Mit Blick auf die /usr/share/php/PHPUnit/TextUI/TestRunner.php Datei, die ich auf meinem System, ich sehe das (Linie 198 und folgende) :

if (!$arguments['convertNoticesToExceptions']) {
    PHPUnit_Framework_Error_Notice::$enabled = FALSE;
}

if (!$arguments['convertWarningsToExceptions']) {
    PHPUnit_Framework_Error_Warning::$enabled = FALSE;
}

Also vielleicht werden Sie irgendeine Art von Parametern übergeben müssen, um dieses Verhalten zu aktivieren? Aber es scheint standardmäßig ...

aktiviert werden

Eigentlich gibt es eine Möglichkeit, sowohl den Rückgabewert und die Ausnahme geworfen zu testen (in diesem Fall ein Fehler von PHPUnit umgewandelt).

Sie müssen nur Folgendes tun:

public function testLoadFileTriggersErrorWhenFileNotFound()
{
    $this->assertFalse(@load_file('/some/non-existent/file'));

    $this->setExpectedException('PHPUnit_Framework_Error_Warning'); // Or whichever exception it is
    load_file('/some/non-existent/file');
}

Beachten Sie, dass für den Rückgabewert zu testen, haben die Fehlerunterdrückungs Operator auf den Funktionsaufruf zu verwenden (die @ vor dem Funktionsnamen). Auf diese Weise wird keine Ausnahme ausgelöst werden, und die Ausführung wird fortgesetzt. Sie dann die erwartete Ausnahme wie üblich gesetzt haben, um den Fehler zu testen.

Was Sie nicht tun können, ist Test mehrere Ausnahmen innerhalb einer Unit-Test.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top