Jak symulować zdarzenia, które powodują wyjątki w testowaniu bloków try / catch?

14

Rozumiem, jak działają wyjątki i jak je wychwytywać i obsługiwać w języku C #, ale jak mogę symulować zdarzenia, które mogą powodować wyjątki, aby mieć pewność, że zostaną wychwycone poprawnie? Na przykład, czy można uruchomić aplikację w rodzaju stanowiska testowego, w którym można symulować problemy z siecią, problemy z bazą danych itp.? Wydaje się, że wyjątki z natury są trudne do odtworzenia, co utrudnia zapewnienie, że Twój kod sobie z nimi poradzi.

Chociaż rozwijam głównie za pomocą C # / .NET / Visual Studio, odpowiedzi lub zasoby dotyczące innych języków mogą być przydatne.

Piers Myers
źródło
Inne możliwe rozwiązanie opisano w tym artykule MSDN: Testowanie wtrysku z błędem za pomocą TestApi
Giorgi

Odpowiedzi:

13

1) Jeśli zastosowałeś model wstrzykiwania zależności, możesz zastąpić rzeczywiste implementacje niektórych części próbami, które rzucałyby wyjątki w razie potrzeby. Wymagałoby to jednak od Ciebie początkowego zaprojektowania aplikacji w określony sposób lub całkowitego jej przeprojektowania.

Lubić:

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

W tym przypadku mielibyśmy jednak problem, że kod konsumenta nie powinien zajmować się obsługą konkretnych wyjątków implementacyjnych.

2) Innym podejściem jest zastąpienie niektórych wywołań metod niestandardowymi opakowaniami.

Zamiast:

FileStream fs = File.OpenRead (path);

używasz:

FileStream fs = File.OpenRead_Test (path);

podając niestandardową metodę rozszerzenia (szybki pomysł):

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

źródło
3

Musisz przyjrzeć się kpiącym ramom.

Za ich pomocą używasz wstrzykiwania zależności, aby wywołać fałszywą bazę danych (powiedzmy) zamiast prawdziwej. Oznacza to, że masz całkowitą kontrolę nad tym, co zostanie zwrócone za każde połączenie.

Następnie konfigurujesz test, który po wywołaniu zgłasza pożądany wyjątek:

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

Test kończy się pomyślnie, gdy Twój kod poprawnie to obsłuży.

ChrisF
źródło
3

Kpiny i zastrzyki mogą cię do tej pory doprowadzić i wymagają w niektórych przypadkach dużych zmian w podejściu.

Jeśli nie chcesz przeprojektowywać aplikacji, aby pasowała do środowiska testowego, to tak naprawdę potrzebujesz hosta lub środowiska przygotowanego na błędy. Istnieje wiele sposobów symulacji spowolnienia sieci w przypadku naszego wyłączenia (nawet narzędzia testowe Microsoft mają tego trochę w obszarze testowania w Internecie). Odniosłem najlepszy sukces, stawiając maszyny za routerem, którym można manipulować w celu zmiany symulacji we współpracy z zestawem bazy danych do generowania błędów i skryptów zmieniających błędy, które produkuje baza danych.

Nawet jeśli pójdziesz wystarczająco szybko lub wystarczająco daleko w stronę sprzętu, pojawią się błędy, takie jak problemy z współbieżnością i opóźnienia zapisu, których prawie nie możesz zasymulować. Czasami musisz je wywoływać naprawdę, a innym razem po prostu musisz pracować bez siatki bezpieczeństwa.

Rachunek
źródło
Uzgodnione - w niektórych przypadkach nie możesz sobie pozwolić na koszty ogólne wynikające z wstrzyknięcia zależności, na przykład w kodzie wydania. To nie jest codzienny problem, ale może się zdarzyć.
Steve314,