Wie verwende ich Assert
(oder eine andere Testklasse), um zu überprüfen, ob eine Ausnahme ausgelöst wurde?
Antworten
Zu viele Anzeigen?Für "Visual Studio Team Test" scheint es, dass Sie das Attribut ExpectedException auf die Methode des Tests anwenden.
Ein Beispiel aus der Dokumentation finden Sie hier: Ein Exkurs zu Unit-Tests mit Visual Studio Team Test
[TestMethod]
[ExpectedException(typeof(ArgumentException),
"A userId of null was inappropriately allowed.")]
public void NullUserIdInConstructor()
{
LogonInfo logonInfo = new LogonInfo(null, "P@ss0word");
}
Normalerweise hat Ihr Testsystem eine Antwort darauf. Aber wenn es nicht flexibel genug ist, können Sie dies immer tun:
try {
somethingThatShouldThrowAnException();
Assert.Fail(); // If it gets to this line, no exception was thrown
} catch (GoodException) { }
Wie @Jonas anmerkt, funktioniert dies NICHT, um eine Base Exception zu fangen:
try {
somethingThatShouldThrowAnException();
Assert.Fail(); // raises AssertionException
} catch (Exception) {
// Catches the assertion exception, and the test passes
}
Wenn Sie unbedingt eine Exception abfangen müssen, müssen Sie die Assert.Fail() erneut auslösen. Aber das ist wirklich ein Zeichen dafür, dass Sie das nicht von Hand schreiben sollten. Überprüfen Sie Ihr Test-Framework auf Optionen oder schauen Sie, ob Sie eine sinnvollere Ausnahme auslösen können, auf die Sie testen können.
catch (AssertionException) { throw; }
Sie sollten in der Lage sein, diesen Ansatz so anzupassen, wie Sie es wünschen - einschließlich der Angabe, welche Arten von Ausnahmen abgefangen werden sollen. Wenn Sie nur bestimmte Typen erwarten, beenden Sie die catch
blockiert mit:
} catch (GoodException) {
} catch (Exception) {
// not the right kind of exception
Assert.Fail();
}
Meine bevorzugte Methode für die Implementierung dieser ist eine Methode namens Throws zu schreiben, und verwenden Sie es genau wie jede andere Assert-Methode. Leider erlaubt es .NET nicht, eine statische Erweiterungsmethode zu schreiben, so dass Sie diese Methode nicht so verwenden können, als ob sie tatsächlich zur eingebauten Assert-Klasse gehört; erstellen Sie einfach eine andere mit dem Namen MyAssert oder etwas Ähnlichem. Die Klasse sieht wie folgt aus:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace YourProject.Tests
{
public static class MyAssert
{
public static void Throws<T>( Action func ) where T : Exception
{
var exceptionThrown = false;
try
{
func.Invoke();
}
catch ( T )
{
exceptionThrown = true;
}
if ( !exceptionThrown )
{
throw new AssertFailedException(
String.Format("An exception of type {0} was expected, but not thrown", typeof(T))
);
}
}
}
}
Das bedeutet, dass Ihr Unit-Test wie folgt aussieht:
[TestMethod()]
public void ExceptionTest()
{
String testStr = null;
MyAssert.Throws<NullReferenceException>(() => testStr.ToUpper());
}
Das sieht und verhält sich viel mehr wie der Rest Ihrer Unit-Test-Syntaxen.
Wenn Sie NUNIT verwenden, können Sie etwa so vorgehen:
Assert.Throws<ExpectedException>(() => methodToTest());
Es ist auch möglich, die ausgelöste Ausnahme zu speichern, um sie weiter zu validieren:
ExpectedException ex = Assert.Throws<ExpectedException>(() => methodToTest());
Assert.AreEqual( "Expected message text.", ex.Message );
Assert.AreEqual( 5, ex.SomeNumber);
MSTest (v2) hat jetzt eine Assert.ThrowsException-Funktion, die wie folgt verwendet werden kann:
Assert.ThrowsException<System.FormatException>(() =>
{
Story actual = PersonalSite.Services.Content.ExtractHeader(String.Empty);
});
Sie können es mit nuget installieren: Install-Package MSTest.TestFramework
- See previous answers
- Weitere Antworten anzeigen