Wie können Ereignisse simuliert werden, die Ausnahmen zum Testen von Try / Catch-Blöcken verursachen?

14

Ich verstehe, wie Ausnahmen funktionieren und wie sie in C # abgefangen und behandelt werden, aber wie kann ich Ereignisse simulieren, die möglicherweise eine Ausnahme verursachen, um sicherzustellen, dass sie korrekt abgefangen wird? Ist es beispielsweise möglich, eine Anwendung in einer Art Testumgebung auszuführen, in der Netzwerkprobleme, Datenbankprobleme usw. simuliert werden können? Ausnahmen sind naturgemäß schwer zu reproduzieren, sodass es schwierig ist, sicherzustellen, dass Ihr Code mit ihnen fertig wird.

Obwohl ich hauptsächlich mit C # /. NET / Visual Studio entwickle, können Antworten oder Ressourcen zu anderen Sprachen hilfreich sein.

Piers Myers
quelle
Eine andere mögliche Lösung wird in diesem MSDN-Artikel beschrieben: Fehlerinjektionstests mit TestApi
Giorgi

Antworten:

13

1) Wenn Sie dem Abhängigkeitsinjektionsmodell folgen, können Sie reale Implementierungen bestimmter Teile durch die Mocks ersetzen, die bei Bedarf Ausnahmen auslösen. Dazu müssten Sie Ihre Anwendung jedoch zunächst spezifisch gestalten oder komplett überarbeiten.

Mögen:

public class SqlUsersRepository : IUsersRepository
{
    public void RegisterNewUser (User newUser)
    {
        throw new SqlException ("Connection timeout");
    }
}

Hier hätten wir jedoch das Problem, dass sich der Consumer Code nicht mit konkreten Implementierungsausnahmen befassen sollte.

2) Ein weiterer Ansatz besteht darin, bestimmte Methodenaufrufe durch Ihre benutzerdefinierten Wrapper zu ersetzen.

Anstatt von:

FileStream fs = File.OpenRead (path);

Sie nutzen:

FileStream fs = File.OpenRead_Test (path);

durch Angabe einer benutzerdefinierten Erweiterungsmethode (nur eine kurze Vorstellung):

public static FileStream OpenRead_Test (this System.IO.File file, string path)
{
    throw new FileNotFoundException ();
}

quelle
3

Sie müssen sich Spott-Frameworks ansehen.

Bei diesen verwenden Sie die Abhängigkeitsinjektion, um die gefälschte Datenbank (etwa) und nicht die reale Datenbank aufzurufen. Dies bedeutet, dass Sie die vollständige Kontrolle darüber haben, was für jeden Anruf zurückgegeben wird.

Anschließend richten Sie einen Test ein, der beim Aufruf einfach die gewünschte Ausnahme auslöst:

public void Test1()
{
    throw new NullArgumentException();
}

Ihr Test ist bestanden, wenn Ihr Code dies korrekt handhabt.

ChrisF
quelle
3

Das Verspotten und Spritzen kann Sie nur so weit bringen und erfordert in einigen Fällen große Änderungen in der Herangehensweise.

Wenn Sie Ihre App nicht an ein Testframework anpassen möchten, benötigen Sie einen Host oder eine Umgebung, die auf Fehler ausgelegt ist. Es gibt viele Möglichkeiten, die Netzwerk-Langsamkeit unseres Ausfalls zu simulieren (auch Microsoft-Testtools haben im Web-Testbereich ein wenig davon). Ich hatte den besten Erfolg damit, Maschinen hinter einen Router zu stellen, der manipuliert werden kann, um Simulationen in Abstimmung mit einem Datenbanksatz zu ändern, um Fehler zu erzeugen, und Skripte, um die Fehler zu ändern, die die Datenbank erzeugt.

Selbst wenn Sie schnell genug oder weit genug in Richtung Hardware gehen, gibt es Fehler wie Parallelitätsprobleme und verzögerte Schreibfehler, die Sie so gut wie nicht simulieren können. Manchmal muss man sie wirklich verursachen und manchmal muss man nur ohne Sicherheitsnetz arbeiten.

Rechnung
quelle
Einverstanden - in einigen Fällen können Sie sich beispielsweise den Aufwand für die Abhängigkeitsinjektion in Ihrem Release-Code nicht leisten. Kein alltägliches Problem, aber es kann passieren.
Steve314