2009-09-28 16 views
6

Piszę pakiet testów jednostkowych, aby przetestować bibliotekę komunikacyjną TCP/IP.Jak obsługiwać wyjątek w wątku tła podczas testu jednostkowego?

Ponieważ używam BeginAcceptClient i EndAcceptClient, wiadomości są odbierane w wątku tła.

Po otrzymaniu wiadomości wykonuję na niej pewne potwierdzenia, ale jeśli jakikolwiek asercja nie powiedzie się, plik VSTestHost.exe ulega awarii.

Przeszukałem trochę i przekonałem się, że wyjątki Assert są zgłaszane w wątku tła.

EDIT: Kod próbka tego, co robię, po prostu ilustrate:


public void TestFooMessage() { 
    Server.OnReceive += (s, e) => { 
     Assert.IsInstanceOfType(e.Message, typeof(Foo)); 
    }; 

    var message = new Foo(); 
    Client.Send(message); 
} 

Czy ktoś wie jak zrobić to działa zgodnie z oczekiwaniami: Zaloguj twierdzenie i nadal działa normalnie?

Odpowiedz

6

Nie należy napisać twierdzi w wątku tła (słownie: obsługi zdarzeń tło), ponieważ struktura testowa nie może tego obsłużyć. Powinieneś tam tylko gromadzić wartości. Możesz zsynchronizować główny wątek na przykład za pomocą AutoResetEvents. Zapisz wartości w polach, potwierdzaj pola w głównym wątku.

Jeśli wiadomości nigdy nie nadchodzą, potrzebujesz limitu czasu.

Kod nieco pseudo (właściwie to nie pseudo):

private AutoResetEvent ReceiveEvent = new AutoResetEvent(false); 
private EventArgs args; 
private bool ReceiveCalled = false; 

// event handler with some argument 
private void Receive(object sender, EventArgs args) 
{ 
    // get some arguments from the system under test 
    this.args= args; 

    // set the boolean that the message came in 
    ReceiveCalled = true; 

    // let the main thread proceed 
    ReceiveEvent.Set(); 
} 

[TestMethod] 
public void Test() 
{ 
    // register handler 
    Server.OnReceive += Receive; 

    var message = new Foo(); 
    Client.Send(message); 

    // wait one second for the messages to come in 
    ReceiveEvent.WaitOne(1000); 

    // check if the message has been received 
    Assert.IsTrue(
    ReceiveCalled, 
    "AcceptClientReceived has not been called"); 

    // assert values from the message 
    Assert.IsInstanceOfType(args.Message, typeof(Foo))  
} 

Nawiasem mówiąc: nadal można napisać procedurę obsługi jako wyrażenie lambda a nawet uniknąć pola za pomocą zmiennych lokalnych. Ale może być trudniej przeczytać, czy wszystko jest w jednej metodzie.

1

Podejrzewam będziesz w zasadzie potrzebne jakieś „wszystko w porządku” Bandera:

  1. utworzyć tę globalną flagę i ustawić go prawda na początku testu
  2. Napisz równoległego Assert metody która usuwa flagę i może ustawia inną zmienną dla "powodu" (lub dodaje ją do listy), a następnie kończy wątek czysto (jeśli to możliwe)
  3. Ustaw główny wątek testowy, czekając na zakończenie wszystkich pozostałych wątków, a następnie sprawdź Flaga.

Jest możliwe, że niektóre ramy testowe to wbudowane, ale nie wiem, z dowolnego bezceremonialny ...

+1

Problem polega na tym, że wątki są tworzone przez testowany system. Zwykle ich nawet nie znasz, chyba że zostaniesz oddzwoniony. Nie ma ogólnego rozwiązania dla gwintów tła w testach jednostkowych. –

+1

Poczekaj na zdarzenie w funkcji testu i ustaw zdarzenie w asynchronicznym wywołaniu zwrotnym. –

0

Próbowałem co Stefan zaproponował oraz następujące prace dla mnie:

public void TestFooMessage() { 
    Foo message = null; 
    var resetEvent = new AutoResetEvent(false); 

    Server.OnReceive += (s, e) => { 
     message = e.Message; 
     resetEvent.Set(); 
    }; 

    var message = new Foo(); 
    Client.Send(message); 

    if (resetEvent.WaitOne(1000)) { 
     Assert.IsInstanceOfType(e.Message, typeof(Foo)); 
    } else { 
     Assert.Fail("Foo not received!"); 
    } 
} 

Dzięki!

Powiązane problemy