2012-05-22 10 views
8

Mam zestaw testów integracji, które używają System.Net.HttpClient. Większość naszych sekcjach „akt” w tych testach używać tego ogólnego wzoru:Jak mogę obsługiwać wyjątki asynchroniczne przy użyciu System.Net.Http.HttpClient z moimi testami integracji?

// Arrange 
// Do some stuff 

// Act 
var download = _client 
    .GetStringAsync(testUrl) 
    .Result; 

// Assert 
// Does "download" contain what I expected? 

Jednak prowadzenie tych badań sporadycznie daje coś takiego:

System.AggregateException : One or more errors occurred. 
    ----> System.Threading.Tasks.TaskCanceledException : A task was canceled. 
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) 
at System.Threading.Tasks.Task`1.get_Result() 

Zdaję sobie sprawę, używając HttpClient jest przeznaczona dla skopując rzeczy async i nie jest idealnie dopasowany do naszych scenariuszy testów integracyjnych, w których zawsze musimy czekać. Więc to prowadzi mnie do dwóch pytań, które są nieco powiązanych:

  1. Czy korzystanie HttpWebRequest/HttpWebResponse bardziej odpowiedni dla tego scenariusza?
  2. Nawet jeśli tak jest, to jaki jest najlepszy sposób pracy z HttpClient, aby obsługiwać błędy na prośbach uruchamianych asynchronicznie?
+0

Dlaczego robisz to asynchronicznie na początek? Wygląda na to, że chcesz to zrobić synchronicznie ... więc powiedziałbym "tak", aby zadać pytanie nr 1. W przypadku pytania nr 2 zwiększyłbym właściwość 'Timeout' klasy HttpClient, chyba że musisz przetestować czas reakcji w określonym przedziale czasowym. Tak czy siak, nie jestem pewien, dlaczego async byłby lepiej przystosowany do testowania jednostkowego ... – Tom

+1

Httpclient dostarcza tylko metody asynchroniczne. OP poprawnie konwertuje je do wywołań synchronicznych, wywołując Wynik w zadaniu. to również ściśle oznacza, że ​​nie jest to wyjątek asynchroniczny, jest to wyjątek synchroniczny generowany po zablokowaniu na "Wynik". Spróbuję zwiększyć czas oczekiwania. – aL3891

Odpowiedz

3

Zgodnie z sugestiami poprzednich komentatorów połączenie prawdopodobnie kończy się z czasem. Możesz ustawić limit czasu za pomocą _client.Timeout = timeoutInMilliseconds przed wykonaniem wywołania GetStringAsync. Jeśli jednak jest to obecnie ustawienie domyślne (100 sekund), to domyślam się, że zdalny serwer, na którym testujesz, jest faktycznie wyłączony, kiedy to nastąpi.

Więcej informacji na temat właściwości Timeout można znaleźć na stronie: http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.timeout.aspx

1

System.AggregateException pochodzi z wyjątkami, które zdarzają się w perspektywie zadań synchronicznie. Korzystanie z testów async pozwala runnerowi (w moim przypadku NUnit) rozłożyć zadanie i uzyskać prawdziwy wyjątek. Więc co powyższy kod powinien już wyglądało to w ten sposób:

[Test] 
public async Task DownloadContainsWhatIExpected() 
{ 
    // Arrange 
    // Do some stuff 

    // Act 
    var download = await _client 
     .GetStringAsync(testUrl); 

    // Assert 
    // Does "download" contain what I expected? 
} 

Korzystanie async Task w podpis metody i następnie await sprawie połączeń asynchronicznych jest najlepszym sposobem na wykonanie tego rodzaju testów.

+0

Dokładnie tak! Po prostu założyłem, że platformy testów jednostkowych nie są kompatybilne z async/await i używałem .Wait() i .Result. Dzięki za ustawienie mnie prosto! – Skrymsli

Powiązane problemy