2013-07-25 23 views
5

Pracuję nad automatyzacją testów dla usługi i znalazłem sposób na zwinięcie jakiejś typowej konfiguracji weryfikacji & w klasie "sesji".Jak mogę sprawdzić, czy wyjątek został już zgłoszony?

koncepcyjnej precedensowe może wyglądać następująco:

using (var managerSession = new Session(managerRole)) 
{ 
    // A manager puts some items in warehouse 
} 

using (var employeeSession = new Session(employeeRole)) 
{ 
    // An employee moves items from warehouse to store 
} 

using (var customerSession = new Session(customerRole)) 
{ 
    // A customer can buy items from the store 
} 

W konstruktorze obiektu Sesja I ustanowienia połączenia z usługą mam testowanie z właściwego uwierzytelniania za rolę etc, aw Zużyty sesji() Metoda Mam wspólny blok sprawdzania poprawności, który na przykład sprawdza, czy nie wystąpiły błędy po stronie serwera lub ostrzeżenia podczas sesji.

Oczywiście, jest to pewnego rodzaju nadużywanie wzorca IDispose, a jeśli kod testowy w blokach przy użyciu zgłasza wyjątek ORAZ blok sprawdzania poprawności również zgłasza wyjątek, drugi wyjątek zamaskuje pierwszy.

koncepcyjnym, jeśli mamy ten scenariusz:

using (var managerSession = new Session(managerRole)) 
{ 
    Assert.IsTrue(managerSession.DoJob(), "Manager did not do his job"); 
} 

... i assert nie powiedzie się lub wywołanie managerSession.DoJob() zgłasza wyjątek, następnie chciałbym metody Session Dispose() do pomiń blok walidacji, czyli

public void Dispose() 
{ 
    if (NoExceptionThrown()) 
    { 
     Assert.IsFalse(this.serviceConnection.HasErrors(), "Service connection has errors"); 
    } 

    this.serviceConnection.Dispose(); 
} 

... taki, że metoda badania nie powiedzie się z „połączenie z usługą zawiera błędy”, jeśli rzeczywiście nie powiedzie się z „Menedżer nie wykonywać swoją pracę”

Moje pytanie brzmi: Czy jest w ogóle możliwe wdrożenie metody "NoExceptionThrown()"? Czy istnieje jakaś globalna właściwość, którą można sprawdzić, lub coś ukrytego w wątku.CurrentThread, które można wykorzystać?

Aktualizacja:

Moje pytanie brzmi nie jak byłaby to :-)

Mógłbym oczywiście użyć tego wzoru Zamiast:

Session.ForRole(managerRole, (session) => { /* Test code here */ }); 

ze statycznym sposobem ForRole() zdefiniowany jako

public static void ForRole(Role r, Action<Session> code) 
{ 
    var session = new Session(r); 
    try 
    { 
     code(session); 
     Assert.IsFalse(session.serviceConnection.HasErrors()); 
    } 
    finally 
    { 
     session.Dispose(); 
    } 
} 

Ciekaw jestem, czy istnieje jakiś sposób na uchwycenie stanu wyjątku, jak opisano powyżej.

+2

Dwie rzeczy. Po pierwsze, tak, to nadużywa 'IDisposable'. Użyj "IDisposable", aby powiedzieć "Posiadam niezarządzanego zasobu, który powinien zostać uwolniony tak szybko, jak to możliwe". Zrobienie tego oznacza coś innego, co sprawia, że ​​twój kod jest trudny do odczytania. Po drugie, czy niepokoi cię * każdy * wyjątek, czy tylko * nieprzechwycony * wyjątki? Załóżmy, że kod testowy zgłasza wyjątek, przechwytuje go i kończy normalnie. Czy powinno to być oflagowane? –

+0

Ah, martwię się jedynie wyjątkami. Uaktualnię to pytanie ... – Christoffer

+0

Co do nadużywania IDisposable: w rzeczywistości bardziej martwię się brakiem wspólnego sprawdzania poprawności dla każdej sesji niż potencjalnym maskowaniem błędów, więc to pytanie jest bardziej "przyjemne w utrzymaniu". Rzeczywiste bloki kodu testowego to 10-100 linii kodu automatyzacji interfejsu użytkownika, a wykryliśmy już wykryte defekty niewykryte, ponieważ jeden z kroków sprawdzania poprawności został pominięty w jednym z bloków (lub zgłoszony w niewłaściwym bloku). – Christoffer

Odpowiedz

1

Byłoby pomocne, gdyby nie było przeciążenie IDisposable.Dispose która odbyła parametr typu Exception aby wskazać, co jest wyjątkiem, jeśli w ogóle, jest w toku w kontekście finally związanego z jej czyszczenia.Podczas gdy metoda Dispose zasadniczo nie powinna zajmować się szczegółami wyjątku, mogą pojawić się warunki podczas metody, która powinna być zgłaszana do wywołującego. Każdy wyjątek zgłoszony przez Dispose zastąpi każdy wyjątek, który był w toku w kontekście dzwoniącego finally, więc byłoby pomocne, gdyby metoda Dispose mogła enkapsulować oczekujący wyjątek przed jego zastąpieniem. Niestety, taka funkcja nie istnieje i nie oczekuję, że zostaną dodane.

Chociaż istnieje kilka hacków, które mogą zostać użyte do osiągnięcia czegoś podobnego do pożądanego efektu, jedyną semantycznie poprawną metodą jest, aby wyjątek był parametrem metody Dispose. Problem z jakimkolwiek innym podejściem polega na tym, że kod Dispose może być uruchamiany z wielu bloków zagnieżdżonych, z których pewne mają oczekujące wyjątki, a niektóre z nich nie; kod, który bada kontekst wykonania w celu określenia statusu najgłębiej zagnieżdżonego bloku, może się nie udać, jeśli ten blok nie jest tym, który chroni czas życia obiektu, który jest usuwany.

+0

Myślę, że przyjmuję tę odpowiedź jako najbardziej poprawną – Christoffer

0

Jednym, pewnym, ale brzydkim sposobem na to jest posiadanie boola (domyślnie false) na twojej klasie.

using (var managerSession = new Session(managerRole)) 
{ 
    Assert.IsTrue(managerSession.DoJob(), "Manager did not do his job"); 
    managerSession.NoExceptionThrown = true; 
} 

Nie wydaje mi się, że dzięki swojemu IDisposable będziecie robić o wiele czystsze.

W tym przypadku spróbuj ... catch ... w końcu może działać lepiej, ponieważ masz bezpośredni dostęp do obiektu wyjątku, który możesz przetestować pod kątem null-ness (czy to słowo?) I ewentualnie przechowuj go nawet do późniejszego wykorzystania. Nie powinieneś niczego tracić, ponieważ using jest po prostu cukrem, by wreszcie spróbować złapać.

+1

Tak, nullness to doskonale cromulentne słowo. – Christoffer

+0

Co ważniejsze, ustawienie właściwości, która kontroluje blok sprawdzania poprawności w metodzie Dispose, w rzeczywistości nie jest dobrym pomysłem. Jeśli dodamy coś do każdego bloku-użycia, to lepiej byłoby zmienić istniejący kod walidacji na osobną metodę i po prostu wywołać to przed zamknięciem zakresu. – Christoffer

+0

@Christoffer Tak, myślę, że próbujesz zrobić Round-plug-into-a-square-hole rzecz z użyciem. Jak podkreślił supercat, właściwym sposobem jest przekazanie obiektu wyjątku lub wskazanie, czy wystąpił wyjątek w celu utylizacji. Sądzę, że mógłbyś dodać odpowiednią metodę, po prostu zrezygnujesz z używania i sam wywołasz Dispose (wyjątek)? Są też problemy, i nie sądzę, że będziesz w stanie wymusić na języku, aby zrobił dokładnie to, co chcesz, bez patroszenia go i przywracania głowy do tyłu: c. O ile wiem, nie ma możliwości sprawdzenia wyjątków poza blokiem catch. – Xcelled194

Powiązane problemy