2012-05-22 12 views
8

Estoy ejecutando un conjunto de pruebas de integración que usan System.Net.HttpClient. La mayor parte de nuestras secciones "Ley" en estas pruebas utilizan este formato general:¿Cómo puedo manejar excepciones asíncronas usando System.Net.Http.HttpClient con mis pruebas de integración?

// Arrange 
// Do some stuff 

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

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

Sin embargo, la ejecución de estas pruebas de forma intermitente produce algo como esto:

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

Soy consciente usando HttpClient se entiende por dando inicio a las cosas asincrónico y no es perfecto para nuestros escenarios de prueba de integración donde siempre le pedimos que espere. Así que esto me lleva a dos preguntas que son de alguna manera relacionado:

  1. Es usar HttpWebRequest/HttpWebResponse más apropiado para este escenario?
  2. Incluso si lo es, ¿cuál es la mejor manera de trabajar con HttpClient para manejar los errores en las solicitudes iniciadas de forma asincrónica?
+0

¿Por qué estás haciendo esto de forma asíncrona para empezar? Parece que querrías hacerlo sincrónicamente ... así que diría que sí a la pregunta n. ° 1. Para la pregunta n. ° 2, aumentaría la propiedad 'Timeout' de la clase HttpClient, a menos que sea necesario probar la capacidad de respuesta dentro de un determinado período de tiempo. De cualquier forma, no estoy seguro de por qué la sincronización sería más adecuada para las pruebas unitarias ... – Tom

+1

Httpclient solo proporciona métodos asíncronos. OP está convirtiéndolos correctamente en llamadas sincrónicas llamando a Result en la tarea. esto también estrictamente hablando significa que esta no es una excepción asíncrona, es una excepción sincrónica lanzada después del bloqueo en "Resultado". Intentaría aumentar el tiempo de espera – aL3891

Respuesta

3

Como sugirieron los comentaristas anteriores, es probable que su conexión se agote. Puede establecer el tiempo de espera con _client.Timeout = timeoutInMilliseconds antes de realizar la llamada GetStringAsync. Sin embargo, si actualmente es el valor predeterminado (100 segundos), supongo que el servidor remoto con el que está probando está realmente inactivo cuando esto ocurre.

Más información acerca de la propiedad de tiempo de espera se puede encontrar en: http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.timeout.aspx

1

System.AggregateException proviene de excepciones que suceden en la ejecución de una tarea de forma sincrónica. El uso de pruebas asíncronas permite que el corredor (en mi caso, NUnit) descomponga la tarea y llegue a la excepción real. Entonces, ¿el código anterior debería haber parecido es la siguiente:

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

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

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

Usando async Task en la firma del método y luego await en las llamadas asíncronas es la mejor manera de ejecutar este tipo de pruebas.

+0

¡Exactamente correcto! Simplemente asumí que los marcos de prueba de la unidad no eran compatibles con async/await y estaba usando .Wait() y .Result. ¡Gracias por corregirme! – Skrymsli

Cuestiones relacionadas