Nunit, weder Assert.WOWS noch [erwartungsgemäß] Fang geworfene Ausnahme
Frage
Bevor ich anfange, möchte ich klarstellen, dass ich bereits nach Lösungen in beiden überprüft habe diese Frage und diese Frage.
Die Methode zum Testen
public static DataSet ExecuteDataSet(this SqlConnection connection, string sql)
{
if (null == connection || null == sql)
{
throw new ArgumentNullException();
}
using (var command = connection.CreateCommand())
{
// Code elided for brevity
}
}
Die Testmethoden
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void ExecuteDataSetThrowsForNullConnection()
{
((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
}
[Test]
public void ExecuteDataSetThrowsForNullSql()
{
Assert.Throws<ArgumentNullException>(
() => Resource.Connection.ExecuteDataSet(null)
);
}
Das seltsame Verhalten
Weder Version der Prüfung Methode fängt die auf ArgumentNullException
das wird sofort beim Betreten der ExecuteDataSet
Methode. Der Steuerfluss verläuft zur nächsten Zeile (using (var command = connection.CreateCommand())
) und ein NullReferenceException
findet stattdessen statt (was natürlich nicht von einem meiner Testfälle behandelt wird, weil Es sollte niemals geworfen werden).
Ursprünglich die erste Testmethode (ExecuteDataSetThrowsForNullConnection
) sah genauso aus wie der zweite (ExecuteDataSetThrowsForNullSql
). Wann Assert.Throws
Ich habe die Ausnahme nicht erfasst, ich habe einige Nachforschungen angestellt und festgestellt, dass einige Leute es empfohlen haben ExpectedException
stattdessen. Ich habe den Testcode entsprechend geändert, aber ohne Erfolg.
Für den Datensatz ist dies 32-Bit-.NET 3.5-Code, getestet unter Nunit 2.5.9. Ich verwende testDriven.net für die Visual Studio -Integration und habe die neuesten Versionen von NCOVER und NDEPEND installiert.
Tl; Dr -Frage
Warum fangen die Testmethoden nicht die Ausnahme auf, die ausgelöst wird, und wie repariere ich sie?
BEARBEITEN
Diese Version der Testmethode funktioniert.
[Test]
public void ExecuteDataSetThrowsForNullConnection()
{
try
{
((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
}
catch(ArgumentNullException e)
{
Assert.AreEqual(true, true);
}
catch (Exception e)
{
Assert.Fail("Expected ArgumentNullException, but {1} was thrown instead.", e.GetType().Name);
}
}
Lösung
Ich vermute, dass Sie den Code, den Sie glauben, nicht wirklich testen. Versuchen Sie, einige zu setzen Console.WriteLine
Aussagen in und prüfen Sie, ob sie gedruckt sind. Wenn Sie einen Haltepunkt auf die throw
Erklärung und führen Sie die Tests im Debugger aus, wird der Haltepunkt getroffen? Wenn die Kontrolle an die nächste Aussage übergeht, bedeutet dies, dass die Ausnahme niemals ausgelöst wird - sie kann unmöglich auf eine Weise gefangen werden, die die Ausführung in der Wurfmethode fortsetzen lässt, es sei denn Ja wirklich seltsamer CLR -Fehler.
Ich habe geschrieben viele von Code wie diesem und es ist in Nunit nie gescheitert.
Abgesehen davon sehe ich es als gute Praxis, den Parameternamen in ArgumentExceptions aufzunehmen, damit ich geschrieben hätte:
if (connection == null)
{
throw new ArgumentNullException("connection");
}
if (sql == null)
{
throw new ArgumentNullException("sql");
}
Dies hat das unglückliche Problem, langwierig zu sein und die Parameternamen im Code als Zeichenfolgen zu wiederholen ... aber es ist einigermaßen einfach, sich richtig zu machen (insbesondere mit Resharper, die dazu beitragen, die Namen zu validieren), und es könnte wirklich nützlich sein, wenn dies jemals die Produktion auslöst . (Es gibt einige grottige Hacks, um die Argumente auf andere Weise zu validieren, aber ich vermute, Sie möchten diese nicht sehen ...)