Frage Wie kann ich eine erwartete Ausnahme mit einer bestimmten Ausnahmebedingungsnachricht von einer Ressource-Datei in Visual Studio Test testen?


Visual Studio Test kann mithilfe des ExpectedException-Attributs nach erwarteten Ausnahmen suchen. Sie können eine Ausnahme wie folgt übergeben:

[TestMethod]
[ExpectedException(typeof(CriticalException))]
public void GetOrganisation_MultipleOrganisations_ThrowsException()

Sie können auch folgendermaßen nach der Nachricht suchen, die in der ExpectedException enthalten ist:

[TestMethod]
[ExpectedException(typeof(CriticalException), "An error occured")]
public void GetOrganisation_MultipleOrganisations_ThrowsException()

Aber beim Testen von I18N-Anwendungen würde ich eine Ressourcendatei verwenden, um diese Fehlermeldung zu erhalten (eventuell entscheide ich mich sogar dafür, die verschiedenen Lokalisierungen der Fehlermeldung zu testen, aber Visual Studio lässt mich das nicht tun:

[TestMethod]
[ExpectedException(typeof(CriticalException), MyRes.MultipleOrganisationsNotAllowed)]
public void GetOrganisation_MultipleOrganisations_ThrowsException()

Der Compiler wird den folgenden Fehler geben:

Ein Attributargument muss ein sein   konstanter Ausdruck, typeof Ausdruck   oder Array-Erstellungsausdruck von einem   Attribut

Weiß jemand, wie man auf eine Ausnahme prüft, die eine Nachricht von einer Betriebsmittelakte hat?


Eine Option, die ich in Erwägung gezogen habe, ist die Verwendung von benutzerdefinierten Ausnahmeklassen, die jedoch auf häufig gehörten Ratschlägen basieren, wie:

"Erstellen und erstellen Sie benutzerdefinierte Ausnahmen   wenn Sie eine Fehlerbedingung haben   kann programmatisch in a behandelt werden   anders als jede andere existierende   Ausnahme. Andernfalls werfen Sie einen der   bestehende Ausnahmen. " Quelle

Ich erwarte nicht, dass die Ausnahmen im normalen Fluss anders gehandhabt werden (es ist eine kritische Ausnahme, also gehe ich sowieso in den Panik-Modus) und ich denke nicht, dass es für jeden Testfall eine Ausnahme bildet, das Richtige zu tun. Irgendwelche Meinungen?


39
2017-09-22 06:08


Ursprung


Antworten:


Gerade eine Meinung, aber ich würde den Fehlertext sagen:

  • ist ein Teil des Tests, in welchem ​​Fall es von der Ressource "falsch" wäre (sonst könnte es zu einer konsistent entstellten Ressource kommen), also aktualisieren Sie den Test einfach, wenn Sie die Ressource ändern (oder der Test fehlschlägt)
  • ist nicht Teil des Tests, und Sie sollten nur darauf achten, dass es die Ausnahme auslöst.

Beachten Sie, dass die erste Option es Ihnen ermöglichen sollte, mehrere Sprachen zu testen, da Sie mit einer Ländereinstellung arbeiten können.

Wie für mehrere Ausnahmen, bin ich aus C ++ Land, wo das Erstellen von Lasten und Lasten von Ausnahmen (bis zu einem pro throw-Anweisung!) In großen Heirachies akzeptabel ist (wenn nicht üblich), aber .Net-Metadaten-System wahrscheinlich nicht So, also dieser Rat.


7
2017-09-22 06:28



Ich würde empfehlen, anstelle eines Attributs eine Hilfsmethode zu verwenden. Etwas wie das:

public static class ExceptionAssert
{
  public static T Throws<T>(Action action) where T : Exception
  {
    try
    {
      action();
    }
    catch (T ex)
    {
      return ex;
    }
    Assert.Fail("Exception of type {0} should be thrown.", typeof(T));

    //  The compiler doesn't know that Assert.Fail
    //  will always throw an exception
    return null;
  }
}

Dann kannst du deinen Test so schreiben:

[TestMethod]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
{
  OrganizationList organizations = new Organizations();
  organizations.Add(new Organization());
  organizations.Add(new Organization());

  var ex = ExceptionAssert.Throws<CriticalException>(
              () => organizations.GetOrganization());
  Assert.AreEqual(MyRes.MultipleOrganisationsNotAllowed, ex.Message);
}

Dies hat auch den Vorteil, dass überprüft wird, ob die Ausnahme in der Zeile, die Sie erwartet haben, ausgelöst wird, und nicht an irgendeiner Stelle in Ihrer Testmethode.


63
2017-09-22 07:26



Das ExpectedException Message-Argument stimmt nicht mit der Nachricht der Ausnahme überein. Es ist vielmehr die Nachricht, die in den Testergebnissen gedruckt wird, wenn die erwartete Ausnahme nicht tatsächlich aufgetreten ist.


13
2018-01-16 05:40



Ich denke, Sie können einen expliziten try-catch in Ihrem Testcode ausführen, anstatt sich auf das ExpectedException-Attribut zu verlassen, um dies für Sie zu tun. Dann können Sie eine Hilfsmethode erstellen, die die Ressourcendatei liest und die Fehlermeldung mit derjenigen vergleicht, die mit der Ausnahme kommt, die abgefangen wurde. (natürlich, wenn es keine Ausnahme gab, sollte der Testfall als ein Fehler betrachtet werden)


4
2017-09-22 06:15



Wenn Sie auf die sehr schön umschalten xUnit.Net Bibliothek testen, können Sie [ExpectedException] durch etwas wie folgt ersetzen:

[Fact]
public void TestException()
{
   Exception ex = Record.Exception(() => myClass.DoSomethingExceptional());
   // Assert whatever you like about the exception here.
}

3
2017-09-22 06:15



Ich frage mich, ob NUnit sich von der Einfachheit wegbewegt ... aber hier gehst du.

Neue Erweiterungen (2.4.3 und höher?) Für das ExpectedException-Attribut ermöglichen Ihnen mehr Kontrolle über die Prüfungen, die für die erwartete Ausnahme über eine Handler-Methode ausgeführt werden. Weitere Details zum offizielle NUnit Doc-Seite.. gegen Ende der Seite.

[ExpectedException( Handler="HandlerMethod" )]
public void TestMethod()
{
...
}

public void HandlerMethod( System.Exception ex )
{
...
}

Hinweis: Etwas fühlt sich hier nicht richtig an. Warum werden Ihre Ausnahmenmeldungen internationalisiert? Verwenden Sie Ausnahmen für Dinge, die behandelt oder dem Benutzer mitgeteilt werden müssen. Es sei denn, Sie haben eine Gruppe von kulturell verschiedenen Entwicklern, die Fehler beheben. Sie sollten das nicht brauchen. Ausnahmen in Englisch oder eine allgemein akzeptierte Sprache würden ausreichen. Aber falls du das haben musst .. es ist möglich :)


1
2017-09-22 06:46



Ich bin auf diese Frage gestoßen, als ich versucht habe, ein ähnliches Problem alleine zu lösen. (Ich werde die Lösung, auf die ich mich unten geeinigt habe, detailliert beschreiben.)

Ich muss Gishus Kommentaren bezüglich der Internationalisierung der Ausnahmemeldungen, die ein Code-Geruch sind, zustimmen.

Ich hatte dies zunächst in meinem eigenen Projekt getan, damit ich Konsistenz zwischen den Fehlermeldungen meiner Applikation und meiner Unit-Tests bekommen konnte. Um meine Ausnahmebestätigungen nur an einem Ort und zu einer bestimmten Zeit definieren zu müssen, erschien mir die Resource-Datei als sinnvoller Ort, da ich sie bereits für verschiedene Labels und Strings verwendete (und es sinnvoll war, eine Referenz hinzuzufügen) dazu in meinem Testcode zu verifizieren, dass diese gleichen Labels an den entsprechenden Stellen angezeigt werden).

An einem Punkt hatte ich mit try / catch-Blöcken gedacht (und getestet), um das Erfordernis einer Konstante durch das ExpectedException-Attribut zu vermeiden, aber dies schien, als würde es zu einer Menge zusätzlichen Codes führen, wenn es in großem Umfang angewendet wird.

Letztendlich bestand die Lösung, auf die ich mich einigte, darin, eine statische Klasse in meiner Ressourcenbibliothek zu erstellen und darin meine Ausnahmemeldungen zu speichern. Auf diese Weise besteht keine Notwendigkeit, sie zu internationalisieren (was ich zustimmen kann, macht keinen Sinn), und sie werden jederzeit zugänglich gemacht, damit eine Ressourcen-Zeichenfolge zugänglich ist, da sie sich im selben Namensraum befinden. (Dies passt zu meinem Wunsch, den Ausnahmetext nicht zu einem komplexen Prozess zu machen.)

Mein Testcode läuft dann einfach auf (entschuldigen Sie den Mangling ...):

[Test, 
    ExpectedException(typeof(System.ArgumentException),
    ExpectedException=ProductExceptionMessages.DuplicateProductName)]
public void TestCreateDuplicateProduct()
{
    _repository.CreateProduct("TestCreateDuplicateProduct");
    _repository.CreateProduct("TestCreateDuplicateProduct");
} 

0
2018-02-18 22:00