Ich habe ein paar verschiedene Muster, die ich benutze. Ich benutze das ExpectedException
Attribut die meiste Zeit, wenn eine Ausnahme erwartet wird. Dies reicht in den meisten Fällen aus, es gibt jedoch einige Fälle, in denen dies nicht ausreicht. Die Ausnahme ist möglicherweise nicht abfangbar - da sie von einer Methode ausgelöst wird, die durch Reflektion aufgerufen wird - oder ich möchte nur überprüfen, ob andere Bedingungen gelten, z. B. wenn eine Transaktion zurückgesetzt wird oder noch ein Wert festgelegt wurde. In diesen Fällen verpacke ich es in einen try/catch
Block, der die genaue Ausnahme erwartet, eine, Assert.Fail
wenn der Code erfolgreich ist, und generische Ausnahmen abfängt, um sicherzustellen, dass keine andere Ausnahme ausgelöst wird.
Erster Fall:
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void MethodTest()
{
var obj = new ClassRequiringNonNullParameter( null );
}
Zweiter Fall:
[TestMethod]
public void MethodTest()
{
try
{
var obj = new ClassRequiringNonNullParameter( null );
Assert.Fail("An exception should have been thrown");
}
catch (ArgumentNullException ae)
{
Assert.AreEqual( "Parameter cannot be null or empty.", ae.Message );
}
catch (Exception e)
{
Assert.Fail(
string.Format( "Unexpected exception of type {0} caught: {1}",
e.GetType(), e.Message )
);
}
}
Assert.Throws
Methode hat, die beide Fälle abdeckt.Jetzt, 2017, können Sie es mit dem neuen MSTest V2 Framework einfacher machen :
quelle
System.Exception
geworfen wird. Jeder andere, wie ein,System.ArgumentException
wird den Test nicht bestehen.Assert.ThrowsException<MyException>
nur der angegebene Ausnahmetyp und nicht einer der abgeleiteten Ausnahmetypen getestet wird. In meinem Beispiel würde der Test fehlschlagen , wenn der TestSub
aufThrow
einenMyInheritedException
(von der Basisklasse abgeleiteten TypMyException
) wäre .Try { SubToTest(); Assert.Fail("...") } Catch (AssertFailedException e) {throw;} Catch (MyException e) {...}
. Beachten Sie die höchste Bedeutung vonCatch (AssertFailedException e) {throw;}
(vgl. Kommentar von allgeek)Ich bin neu hier und habe nicht den Ruf, Kommentare abzugeben oder abzustimmen, wollte aber auf einen Fehler im Beispiel in Andy Whites Antwort hinweisen :
In allen mir bekannten Unit-Testing-Frameworks
Assert.Fail
wird eine Ausnahme ausgelöst, sodass der generische Fang den Fehler des Tests tatsächlich maskiert. WennSomethingThatCausesAnException()
nicht geworfenAssert.Fail
wird, sprudelt der Wille, aber das wird niemals zum Testläufer heraus, um einen Fehler anzuzeigen.Wenn Sie die erwartete Ausnahme abfangen müssen (dh um bestimmte Details wie die Nachricht / Eigenschaften der Ausnahme zu bestätigen), ist es wichtig, den spezifischen erwarteten Typ und nicht die Basisausnahmeklasse abzufangen. Dies würde es ermöglichen, dass die
Assert.Fail
Ausnahme heraussprudelt (vorausgesetzt, Sie lösen nicht die gleiche Art von Ausnahme aus, die Ihr Unit-Testing-Framework ausführt), ermöglicht jedoch weiterhin die Validierung der Ausnahme, die von IhrerSomethingThatCausesAnException()
Methode ausgelöst wurde .quelle
Ab Version 2.5 verfügt NUnit über die folgenden Methodenebenen
Assert
zum Testen von Ausnahmen:Assert.Throws , das auf einen genauen Ausnahmetyp prüft :
Und
Assert.Catch
, die auf eine Ausnahme eines bestimmten Typs oder einen von diesem Typ abgeleiteten Ausnahmetyp testen:Abgesehen davon möchten Sie beim Debuggen von Komponententests, die Ausnahmen auslösen, möglicherweise verhindern, dass VS die Ausnahme beschädigt .
Bearbeiten
Nur um ein Beispiel für Matthews Kommentar unten zu geben, die Rückgabe des Generikums
Assert.Throws
undAssert.Catch
ist die Ausnahme mit dem Typ der Ausnahme, die Sie dann zur weiteren Prüfung untersuchen können:quelle
Assert.Throws
, außerdem gibt es die Ausnahme zurück, so dass Sie weitere Aussagen über die Ausnahme selbst schreiben können.Leider hat MSTest STILL nur wirklich das ExpectedException-Attribut (zeigt nur, wie sehr sich MS um MSTest kümmert), was IMO ziemlich schrecklich ist, weil es das Arrange / Act / Assert-Muster bricht und es Ihnen nicht erlaubt, genau anzugeben, welche Codezeile Sie für die Ausnahme erwarten auftreten am.
Wenn ich MSTest verwende (/ von einem Client gezwungen), verwende ich immer diese Hilfsklasse:
Anwendungsbeispiel:
quelle
Als Alternative zur Verwendung von
ExpectedException
Attributen definiere ich manchmal zwei hilfreiche Methoden für meine Testklassen:AssertThrowsException()
Nimmt einen Delegaten und behauptet, dass er die erwartete Ausnahme mit der erwarteten Nachricht auslöst.AssertDoesNotThrowException()
Nimmt denselben Delegaten und behauptet, dass er keine Ausnahme auslöst.Diese Kopplung kann sehr nützlich sein, wenn Sie testen möchten, ob in einem Fall eine Ausnahme ausgelöst wird, im anderen jedoch nicht.
Mit ihnen könnte mein Unit-Test-Code folgendermaßen aussehen:
Schön und ordentlich, oder?
Meine
AssertThrowsException()
undAssertDoesNotThrowException()
Methoden werden in einer gemeinsamen Basisklasse wie folgt definiert:quelle
Markieren Sie den Test mit dem ExpectedExceptionAttribute (dies ist der Begriff in NUnit oder MSTest; Benutzer anderer Unit-Test-Frameworks müssen möglicherweise übersetzen).
quelle
Bei den meisten .net-Unit-Test-Frameworks können Sie der Testmethode ein Attribut [ExpectedException] hinzufügen. Dies kann Ihnen jedoch nicht sagen, dass die Ausnahme an dem Punkt aufgetreten ist, den Sie erwartet haben. Das ist , wo xunit.net helfen kann.
Mit xunit haben Sie Assert.Throws, damit Sie folgende Dinge tun können:
[Fakt] ist das Xunit-Äquivalent von [TestMethod]
quelle
Schlagen Sie vor, die saubere Delegatensyntax von NUnit zu verwenden .
Beispiel zum Testen
ArgumentNullExeption
:quelle