Wie überprüfe ich in meinem MSTest-Komponententest, dass keine Ausnahme aufgetreten ist?


87

Ich schreibe einen Unit-Test für diese eine Methode, der "void" zurückgibt. Ich hätte gerne einen Fall, in dem der Test bestanden wird, wenn keine Ausnahme ausgelöst wird. Wie schreibe ich das in C #?

Assert.IsTrue(????)

(Ich vermute, so sollte ich das überprüfen, aber was geht in "???")

Ich hoffe meine Frage ist klar genug.


Verwenden Sie MSTest oder NUnit?
Matt Grande

2
In MSTest führen nicht erfasste Ausnahmen automatisch dazu, dass Tests fehlschlagen. Versuchen Sie, abgefangene Ausnahmen zu berücksichtigen?
Phil

Sie können nach "try-catch for C #" suchen und erfahren, wie Sie mit Ausnahmen umgehen, die ausgelöst oder nicht ausgelöst werden.
Foggzie

1
Wenn NUnit, schauen Sie in Assert.That (Lambda) .Throws.Nothing (obwohl ich denke, dass sich das kürzlich geändert hat)
Matt Grande

Antworten:


136

Ihr Komponententest schlägt ohnehin fehl, wenn eine Ausnahme ausgelöst wird - Sie müssen keine spezielle Zusicherung abgeben.

Dies ist eines der wenigen Szenarien, in denen Unit-Tests ohne Zusicherungen angezeigt werden. Der Test schlägt implizit fehl, wenn eine Ausnahme ausgelöst wird.

Wenn Sie jedoch wirklich eine Behauptung dazu schreiben wollten - vielleicht um die Ausnahme abzufangen und "keine Ausnahme erwartet, aber erhalten ..." zu melden, können Sie dies tun:

[Test]
public void TestNoExceptionIsThrownByMethodUnderTest()
{
    var myObject = new MyObject();

    try
    {
        myObject.MethodUnderTest();
    }
    catch (Exception ex)
    {
        Assert.Fail("Expected no exception, but got: " + ex.Message);
    }
}

(Das Obige ist ein Beispiel für NUnit, aber das Gleiche gilt für MSTest.)


Offensichtlich sollten Sie solche Ausnahmen nicht abfangen, damit dies zutrifft.
Servy

7
Ein Test schlägt nur fehl, wenn eine nicht erfasste Ausnahme ausgelöst wird. Abhängig vom Code in den Ausnahmebehandlungsroutinen können Komponententests bestanden werden.
essbarer Code

1
Es ist nützlich für Frau Unittest, daher gibt es keine Assert.DoesNotThrow (() -Methode in Unittest.
Başar Kaya

25

In NUnit können Sie Folgendes verwenden:

Assert.DoesNotThrow(<expression>); 

um zu behaupten, dass Ihr Code keine Ausnahme auslöst. Obwohl der Test fehlschlagen würde, wenn eine Ausnahme ausgelöst würde, selbst wenn keine Bestätigung vorhanden wäre, besteht der Wert dieses Ansatzes darin, dass Sie in Ihren Tests zwischen nicht erfüllten Erwartungen und Fehlern unterscheiden können und die Option haben, eine benutzerdefinierte Nachricht hinzuzufügen wird in Ihrer Testausgabe angezeigt. Eine gut formulierte Testausgabe kann Ihnen helfen, Fehler in Ihrem Code zu finden, die dazu geführt haben, dass ein Test fehlgeschlagen ist.

Ich denke, es ist gültig, Tests hinzuzufügen, um sicherzustellen, dass Ihr Code keine Ausnahmen auslöst. Stellen Sie sich beispielsweise vor, Sie validieren die Eingabe und müssen eine eingehende Zeichenfolge in eine lange konvertieren. Es kann vorkommen, dass die Zeichenfolge null ist. Dies ist akzeptabel. Sie möchten daher sicherstellen, dass bei der Zeichenfolgenkonvertierung keine Ausnahme ausgelöst wird. Es wird daher Code geben, der diese Gelegenheit behandelt, und wenn Sie keinen Test dafür geschrieben haben, fehlt Ihnen die Abdeckung eines wichtigen logischen Teils.


1
Das explizite DoesNotThrow ist nett. Wenn Sie es gewohnt sind, Assert. * In einem Test zu sehen, denken Sie vielleicht, der andere war faul und hat es vergessen.
Matt Beckman

Gibt es ein Äquivalent dafür in vstest oder mstest?
Dan Csharpster

1
@ DanCsharpster, ich glaube nicht, dass es zumindest in MSTest gibt - wenn ich diese Funktionalität in MSTest in der Vergangenheit benötigt habe, habe ich so etwas getan: public class TestBase { //believe me, I don't like this anymore than you do. protected void AssertDoesNotThrow(Action action, string message) { try { action(); } catch (Exception) { Assert.Fail(message); } } }
Clarkeye

@ Clarkekey, das ist eine interessante Idee. Vielen Dank! Hoffentlich lernen sie, NUnit in zukünftigen Versionen besser zu kopieren. Ich habe auch darüber nachgedacht, einen Adapter zwischen vstest und NUnit zu schreiben.
Dan Csharpster

@DanCsharpster, eine Sache, die Sie sich ansehen sollten, sind fließende Behauptungen, die eine gute Unterstützung für ShouldThrow und ShouldNotThrow bieten: github.com/dennisdoomen/fluentassertions/wiki#exceptions . Die Dokumente sagen, dass es mit MSTest kompatibel ist (obwohl ich es nur mit XUnit und NUnit verwendet habe). Könnte nicht alles tun, was Sie wollen, aber Sie können es trotzdem mit den MSTest-Behauptungen mischen.
Clarkeye

11

Testen Sie nicht, dass etwas nicht passiert . Es ist so, als würde man sicherstellen, dass der Code nicht kaputt geht . Das ist irgendwie impliziert, wir alle streben nach nicht brechendem, fehlerfreiem Code. Sie möchten Tests dafür schreiben? Warum nur eine Methode? Wollen Sie nicht, dass alle Ihre Methoden getestet werden, damit sie keine Ausnahme auslösen ? Wenn Sie dieser Straße folgen, erhalten Sie für jede Methode in Ihrer Codebasis einen zusätzlichen Dummy-Test ohne Assert. Es bringt keinen Wert.

Natürlich, wenn Ihre Anforderung Methode , um zu überprüfen ist tut Ausnahmen fangen , sind Sie testen , ob (oder es etwas rückgängig zu machen ; Test , dass es nicht das, was wirft es zu fangen soll).

Der allgemeine Ansatz / die allgemeinen Praktiken bleiben jedoch erhalten - Sie schreiben keine Tests für einige künstliche / vage Anforderungen, die außerhalb des Bereichs des getesteten Codes liegen (und das Testen, dass "es funktioniert" oder "nicht wirft", ist normalerweise ein Beispiel dafür solche - insbesondere in Szenarien, in denen die Verantwortlichkeiten der Methode bekannt sind).

Um es einfach auszudrücken: Konzentrieren Sie sich darauf, was Ihr Code zu tun hat, und testen Sie dies.


9
-1 Ich kann mir positive Funktionen vorstellen, die erfordern und keine Ausnahme auslösen. Für eine Methode, deren Aufgabe es ist, Ausnahmen zu behandeln, protokollieren und Maßnahmen ergreifen - ohne die Ausnahme weiter auszulösen. Sie machen einen guten allgemeinen Punkt - aber sprechen Sie dann absolut, als ob es immer wahr wäre.
Rob Levine

3
@RobLevine: Ich verstehe Ihr Beispiel und stelle fest, dass Sie in solchen Fällen Tests schreiben. Wie Sie jedoch bemerkt haben, ging es in der Tat um allgemeinere Praktiken - sozusagen darum, zu testen, was Ihr Code tun soll, und zu testen, was Ihr Code nicht tut. Ich habe meinen Beitrag ein wenig umformuliert, damit mein Standpunkt klarer und näher an dem ist, was ich mir vorgestellt habe. Gibt Ihnen auch die Möglichkeit, Ihre Stimme zu überdenken. Vielen Dank für die Klarstellung und entschuldigen Sie die verspätete Antwort.
km

4
Downvote entfernt - Ich werde beim nächsten Down-Voting nicht so glücklich sein!
Rob Levine

3
In unserem Projekt haben wir die htmlvalidator-Klasse, die Ausnahmen auslöst, wenn html nicht gültig ist. Zum Beispiel, wenn Benutzer Javascript (über die Konsole) in einer Rich-Combo eingeben. In meinem Fallcode muss mein Code also keine Ausnahme auslösen (White-List-Ansatz), und ich muss dies testen.
Machet

1
Stimme dieser Antwort nicht zu. Das Testen auf das Fehlen von etwas manchmal unter einem bestimmten Szenario kann ein gültiger Test sein.
Bytedev

6

Diese Helferklasse kratzte mich mit MSTest am Juckreiz. Vielleicht kann es auch deine kratzen.

[TestMethod]
public void ScheduleItsIneligibilityJob_HasValid_CronSchedule()
{
    // Arrange
    var factory = new StdSchedulerFactory();
    IScheduler scheduler = factory.GetScheduler();

    // Assert
    AssertEx.NoExceptionThrown<FormatException>(() =>
        // Act
        _service.ScheduleJob(scheduler)
    );
}

public sealed class AssertEx
{
    public static void NoExceptionThrown<T>(Action a) where T:Exception
    {
        try
        {
            a();
        }
        catch (T)
        {
            Assert.Fail("Expected no {0} to be thrown", typeof(T).Name);
        }
    }
}

@Remco Beurskens - Durch Hinzufügen eines allgemeinen Catch {} am Ende von NoExceptionThrown <T> werden andere Fehler unterdrückt, was keine beabsichtigte Folge der Methode ist. Dies ist keine Allzweckmethode, um alle Ausnahmen zu unterdrücken. Es soll nur fehlschlagen, wenn eine Ausnahme des bekannten Typs ausgelöst wird.
JJS

Dies ist jetzt super alt, hat aber Asserteinen Singleton-Eigenschafts-Accessor, Thatden man als Hook für Erweiterungsmethoden verwenden kann. Es könnte sein , sauberere und mehr auffindbar, zu haben , Assert.That.DoesNotThrow()statt AssertEx.DoesNotThrow(). Dies ist nur eine Meinung.
Richard Hauer

3

Ich mag es, Assert.Whateveram Ende jedes Tests eine zu sehen, nur aus Gründen der Konsistenz ... kann ich ohne eine wirklich sicher sein, dass es dort keine geben soll?

Für mich ist das so einfach wie Putten Assert.IsTrue(true);

Ich weiß, dass ich diesen Code nicht versehentlich dort eingefügt habe, und daher sollte ich sicher genug sein, schnell durchzublättern, dass dies wie beabsichtigt war.

    [TestMethod]
    public void ProjectRejectsGappedVersioningByDefault() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        Assert.Throws<ScriptProject.InvalidProjectFormatException>(() => {
            var sut = new ScriptProject(files);
        });

    }

    [TestMethod]
    public void ProjectAcceptsGappedVersionsExplicitly() {

        var files = new List<ScriptFile>();
        files.Add(ScriptProjectTestMocks.GetVersion1to2());
        files.Add(ScriptProjectTestMocks.GetVersion3to4());

        var sut = new ScriptProject(files, true);

        Assert.IsTrue(true);   // Assert.Pass() would be nicer... build it in if you like

    }

Es ist nicht das gleiche. Wenn Ihr Code ausgelöst wird, wird keine Zusicherung getroffen und Ihr Testlauf schlägt fehl. Sie möchten sich in das Testframework einbinden, indem Sie eine Bedingung bestätigen.
DvS

0

Mein Freund Tim erzählte mir von ExpectedException . Ich mag dieses B / C wirklich, es ist prägnanter, weniger Code und sehr explizit, dass Sie auf eine Ausnahme testen.

[TestMethod()]
[ExpectedException(typeof(System.Exception))]
public void DivideTest()
{
    int numerator = 4;
    int denominator = 0;
    int actual = numerator / denominator;
}

Weitere Informationen hierzu finden Sie hier: Verwendung der ExpectedException-Attribute .


Das OP bittet um eine Ausnahme.
Daniel A. White

Ich werde diese Antwort hier lassen. Ich habe diese Frage gefunden, als ich in Google nach Ausnahmen gesucht habe, und diese Antwort muss meiner Meinung nach hier sein. Die Frage des OP wurde vor 7 Jahren beantwortet. Sogar der Link zu der anderen Antwort finde ich hilfreich.
Jess

Guter alter Tim. 🤔
ruffin
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.