Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I handle async exceptions using System.Net.Http.HttpClient with my integration tests?

I'm running a suite of integration tests that use System.Net.HttpClient. Most of our "act" sections in these tests use this general format:

// Arrange
// Do some stuff

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

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

However, running these tests intermittently yields something like this:

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()

I realize using HttpClient is meant for kicking off things async and isn't a perfect fit for our integration test scenarios where we always tell it to wait. So this leads me to two questions that are somewhat related:

  1. Is using HttpWebRequest / HttpWebResponse more appropriate for this scenario?
  2. Even if it is, what's the best way to work with HttpClient to handle errors on requests kicked off asynchronously?
like image 364
Brandon Linton Avatar asked May 22 '12 21:05

Brandon Linton


2 Answers

As the previous commenters suggested, your connection is probably timing out. You can set the timeout with _client.Timeout = timeoutInMilliseconds before making the GetStringAsync call. However, if it is currently the default (100 seconds) then my guess is that the remote server you are testing against is actually down when this occurs.

More information on the timeout property can be found at: http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.timeout.aspx

like image 95
Micah Zoltu Avatar answered Nov 17 '22 18:11

Micah Zoltu


System.AggregateException comes from exceptions that happen in a task run synchronously. Using async tests allow the runner (in my case, NUnit) to decompose the task and get at the real exception. So what the above code should've looked like is this:

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

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

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

Using async Task in the method signature and then await on the asynchronous calls is the best way to execute these sorts of tests.

like image 41
Brandon Linton Avatar answered Nov 17 '22 18:11

Brandon Linton