NUnit 3.0 und Assert.Throws

70

Ich schreibe einige Unit-Tests mit NUnit 3.0 und im Gegensatz zu v2.x ExpectedException() aus der Bibliothek entfernt.

Basierend darauf Antwort kann ich definitiv die Logik erkennen, wenn ich versuche, genau zu erfassen, wo im Test erwartet wird, dass das System eine Ausnahme auslöst (anstatt nur "irgendwo im Test" zu sagen).

Ich neige jedoch dazu, meine Schritte "Anordnen", "Handeln" und "Durchsetzen" sehr deutlich zu machen, und dies macht es zu einer Herausforderung.

Ich habe so etwas gemacht wie:

[Test, ExpectedException(typeof(FormatException))]
public void Should_not_convert_from_prinergy_date_time_sample1()
{
    //Arrange
    string testDate = "20121123120122";

    //Act
    testDate.FromPrinergyDateTime();

    //Assert
    Assert.Fail("FromPrinergyDateTime should throw an exception parsing invalid input.");
}

Jetzt muss ich etwas tun wie:

[Test]
public void Should_not_convert_from_prinergy_date_time_sample2()
{
    //Arrange
    string testDate = "20121123120122";

    //Act/Assert
    Assert.Throws<FormatException>(() => testDate.FromPrinergyDateTime());
}

Das ist nicht schrecklich, aber meiner Meinung nach trübt es das Gesetz und die Behauptung. (Offensichtlich ist es für diesen einfachen Test nicht schwer zu befolgen, aber bei größeren Tests kann es schwieriger sein).

Ich habe von einem Kollegen vorgeschlagen, dass ich alles los werde Assert.Throwsund einfach so etwas mache wie:

[Test]
public void Should_not_convert_from_prinergy_date_time_sample3()
{
    //Arrange
    int exceptions = 0;
    string testDate = "20121123120122";

    //Act
    try
    {
        testDate.FromPrinergyDateTime();
    }
    catch (FormatException) { exceptions++;}

    //Assert
    Assert.AreEqual(1, exceptions);
}

Hier halte ich mich an das strenge AAA-Format, aber auf Kosten von noch mehr Aufblähung.

Meine Frage geht also an AAA-Tester: Wie würden Sie eine Art Ausnahmevalidierungstest durchführen, wie ich es hier versuche?

Killnine
quelle
1
Wenn die getestete Methode keine Parameter hat, kann Assert folgendermaßen vereinfacht werden: Assert.Throws <FormatException> (testDate.FromPrinergyDateTime) oder Assert.That (testDate.FromPrinergyDateTime, Throws.TypeOf <FormatException> ());
user3285954
Der zweite Teil sieht für mich nicht so aufgebläht aus?
Andrew Day

Antworten:

66

Ich sehe, woher Sie kommen, obwohl es mir nichts ausmacht, in diesem Fall Act / Assert-Schritte zu kombinieren.

Das einzige, was ich mir vorstellen kann, ist, den tatsächlichen Delegaten (hier zu FromPrinergyDateTime) in einer Variablen als "Akt" -Schritt zu speichern und ihn dann zu bestätigen:

[Test]
public void Should_not_convert_from_prinergy_date_time_sample2()
{
    //Arrange
    string testDate = "20121123120122";

    //Act
    ActualValueDelegate<object> testDelegate = () => testDate.FromPrinergyDateTime();

    //Assert
    Assert.That(testDelegate, Throws.TypeOf<FormatException>());
}

Ich verstehe, dass der Schritt "Handeln" nicht wirklich Handeln ist, sondern vielmehr definiert, was die Handlung ist. Es wird jedoch klar umrissen, welche Aktion getestet wird.

Patrick Quirk
quelle
Ahh, das ist eine ziemlich gute Idee. Ich wurde aufgehängt, wie ich die beiden trennen sollte.
Killnine
2
Immer noch nicht wirklich "schauspielern". Erklären Sie einfach, wie Sie handeln möchten.
JamesFaix
Es ist eine großartige Antwort. Ich hatte eine Folgefrage dazu, die ich separat gepostet habe. Möchtest du einen Blick darauf werfen?
Konrad Viltersten
26

In C # 7 gibt es eine andere Option (wenn auch sehr ähnlich zu den vorhandenen Antworten):

[Test]
public void Should_not_convert_from_prinergy_date_time_sample2()
{
    void CheckFunction()
    {
        //Arrange
        string testDate = "20121123120122";

        //Act
        testDate.FromPrinergyDateTime();
    }

    //Assert
    Assert.Throws(typeof(Exception), CheckFunction);
}

Blogbeitrag zum Thema

Paul Michaels
quelle
5
Upvote wegen des Faktors "Was können Sie tatsächlich in c # tun
?
6

Sie können ein benutzerdefiniertes Attribut in NUnit 3 erstellen [ExpectedException]. Hier ist der Beispielcode zum Erstellen eines Attributs. (ExpectedExceptionExample Zeigt, wie ein benutzerdefiniertes Attribut für NUnit implementiert wird.) Https://github.com/nunit/nunit-csharp-samples

Matt Allen
quelle
Genau das habe ich gesucht, danke für den Link!
CrabCRUSHERclamCOLLECTOR
[ExpectedException] ist in NUnit3 veraltet. Verwenden Sie den Assert.That / Throws-Mechanismus.
RvdK
@RvdK Kannst du mich bitte wissen lassen, was der Unterschied zwischen Assert.That und Assert.Throws ist? Ich verstehe den Unterschied zwischen beiden Aussagen nicht wirklich wie unten. Beides funktioniert bei mir .. Aber welches ist besser zu bedienen. Assert.Throws<DataLayerException>(TestDelegate code, "Message"); Assert.That(TestDelegate code, Is.TypeOf<DataLayerException>(), "Message");
VSanka
@ VikranthSanka Assert. Das hat eine bessere Lesbarkeit, das Assert. Das liest natürlicher. Aber es hat auch einige andere Vorteile: objectpartners.com/2013/09/18/…
RvdK