2014-10-15 23 views
10

Jak napisać testów jednostkowych dla async/czekają metody używam Visual Studio 2013.asynchroniczny/czekają jednostka pokrycie kodu testu

Załóżmy, że mamy metodę transmisji asynchronicznej:

public async Task DoSomethingAsync() 
{ 
    ... 
    await _service.DoInternalAsync(); 
    ... 
} 

Ponieważ używam najnowsza wersja programu Visual Studio, ma dobre wsparcie dla testów jednostkowych asynchroniczny metoda:

[TestMethod] 
public async Task DoSomthingAsyncTest() 
{ 
    ... 
    await _objectUnderTest.DoSomethingAsync(); 
    // how to verify the result??? here is what I did 
    _service.Verify(_ => _.DoInternalAsync()); 
} 

Zasadniczo mam dwa pytania:

  1. Jak skomentowano w kodzie, jak zweryfikować wynik Task? Czy zrobiłem to w odpowiedni sposób?
  2. Jeśli uruchomię ten test, VS powie, że test minął. Ale kiedy sprawdzam zasięg kodu, wydaje się, że zdanie await _service.DoInternalAsync() nie jest objęte zakresem, z widoku Code Coverage Results, monit o zdanie MoveNext() ma 6 nieobjętych bloków. Co w tym złego?
+4

Od swojej 'metody async' robi nic innego niż zadania nie wrócić, po prostu stwierdzić, że makiety z' Service' nazwano. Nie ma potrzeby testowania czegokolwiek innego, testy jednostek wewnątrz twojej klasy "service" już obejmują jej zachowanie. Jeśli masz wartość zwracaną, istnieje sposób na wyśmiewanie klas metodami asynchronicznymi. –

Odpowiedz

8

Dobra, z moich badań wynika, że ​​problem z pokryciem kodu jest błędem Visual Studio w najnowszej wersji Visual Studio 2013, naprawili/ulepszyli go w następnej wersji głównej.

Cytat z feedback:

Emisja że widzisz to spowodowane błędem z naszej strony ze względu na które nie mamy pełne wsparcie dla asynchronicznych/czekają wzorca pokrycia kodu jak dotychczas. Prace są w toku i powinny być czymś, co dostarczymy w następnej aktualizacji/wydaniu. Nie ma czystych obejść tego problemu.

+1

Dzięki za poinformowanie nas o oficjalnej opinii. – Emile

2

Przyczyna, dla której kod nie jest pokazany jako objęty, ma związek ze sposobem implementacji metod asynchronicznych. Kompilator C# faktycznie tłumaczy kod w metodach asynchronicznych na klasę, która implementuje automat stanów i przekształca oryginalną metodę w kod pośredniczący, który zainicjował i wywołał ten automat stanów. Ponieważ ten kod jest generowany w zespole, jest uwzględniany w analizie pokrycia kodu.

Jeśli używasz zadania, które nie jest kompletne w momencie, gdy wykonywany jest kod, maszyna wygenerowana przez kompilator pobiera wywołanie zwrotne zakończenia, aby wznowić po zakończeniu zadania. To w pełni wykorzystuje kod maszynowy stanu i powoduje całkowite pokrycie kodu (przynajmniej dla narzędzi pokrycia kodu na poziomie instrukcji).

Typowy sposób na uzyskanie zadania, które nie jest kompletne w danym momencie, ale zakończy się w pewnym momencie, to użycie Task.Delay w teście jednostki. Jednak jest to zazwyczaj zła opcja, ponieważ opóźnienie czasowe jest albo zbyt małe (i powoduje nieprzewidywalne pokrycie kodu, ponieważ czasami zadanie jest zakończone przed uruchomieniem kodu) lub zbyt duże (niepotrzebnie spowalniające testy w dół).

Lepszym rozwiązaniem jest użycie opcji "czekaj na Task.Yield()". To nastąpi natychmiast, ale wywołaj kontynuację, gdy tylko zostanie ustawiona.

Inną opcją - choć nieco absurdalną - jest wdrożenie własnego, godnego zaufania wzorca, który ma semantykę raportowania niekompletną, dopóki połączenie zwrotne nie zostanie nawiązane, a następnie natychmiast zakończone. To zasadniczo zmusza komputer stanu do ścieżki asynchronicznej, zapewniając pełne pokrycie.

Oczywiście nie jest to idealne rozwiązanie.Najbardziej niefortunnym aspektem jest to, że wymaga modyfikacji kodu produkcyjnego w celu ograniczenia ograniczenia narzędzia. Wolałbym, aby narzędzie zasięgu kodu ignorowało części maszyny asynchronicznej generowane przez kompilator. Ale do tego czasu nie ma zbyt wielu opcji, jeśli naprawdę chcesz spróbować uzyskać pełny zasięg kodu.

Pełniejsze wyjaśnienie tego hack, można znaleźć tutaj: http://blogs.msdn.com/b/dwayneneed/archive/2014/11/17/code-coverage-with-async-await.aspx

+0

Podczas gdy ten link może odpowiedzieć na pytanie, lepiej umieścić w nim istotne części odpowiedzi i podać link do odsyłacza. Odpowiedzi dotyczące linków mogą stać się nieprawidłowe, jeśli strona z linkami się zmieni. –

+0

OK, dodałem podsumowanie opcji oraz link do bardziej szczegółowego artykułu. –

Powiązane problemy