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);
    }
}
War es hilfreich?

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 ...)

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