2009-07-23 12 views
20

Estoy usando Xunit y NMock en la plataforma .NET. Estoy probando un modelo de presentación en el que un método es asincrónico. El método crea una tarea asíncrona y la ejecuta de modo que el método retorna inmediatamente y el estado que necesito verificar aún no está listo.¿Hay alguna forma de probar la unidad con un método asíncrono?

Puedo establecer una bandera al terminar sin modificar el SUT, pero eso significaría que tendría que seguir revisando la bandera en un ciclo while, por ejemplo, con quizás tiempo de espera.

¿Cuáles son mis opciones?

+0

.NET no tiene condvars? – jrockway

+0

¿Qué aspecto estás tratando de probar? –

+0

Existen soluciones complicadas, pero si solo es una prueba, entonces no hay nada de malo en una opción de bucle/tiempo de espera/bandera. – Ray

Respuesta

19

¿Tiene su objeto algún tipo de señal de que el método asíncrono está terminado, como un evento? Si ese es el caso, puede utilizar el siguiente enfoque:

[Test] 
public void CanTestAsync() 
{ 
    MyObject instance = new MyObject() 
    AutoResetEvent waitHandle = new AutoResetEvent(false); 
    // create and attach event handler for the "Finished" event 
    EventHandler eventHandler = delegate(object sender, EventArgs e) 
    { 
     waitHandle.Set(); // signal that the finished event was raised 
    } 
    instance.AsyncMethodFinished += eventHandler; 

    // call the async method 
    instance.CallAsyncMethod(); 

    // Wait until the event handler is invoked 
    if (!waitHandle.WaitOne(5000, false)) 
    { 
     Assert.Fail("Test timed out."); 
    } 
    instance.AsyncMethodFinished -= eventHandler;  
    Assert.AreEqual("expected", instance.ValueToCheck); 
} 
+1

Probablemente debería cerrar el identificador de espera cuando termine, ya que utiliza recursos no administrados. Creo que estos recursos se limpiarán automáticamente cuando se recopile el identificador, pero generalmente prefiero ser explícito cuando se utilizan recursos no administrados. –

4

Mi método preferido es simular e inyectar el mecanismo de enhebrado real para que bajo prueba no sea asíncrono. Algunas veces eso no es posible (si el enhebrado del método es parte del marco, o si no está bajo su control).

Si no puede controlar la creación del hilo, entonces espere a que el hilo termine de alguna manera, ya sea un ciclo while o simplemente un tiempo de espera por el tiempo que el hilo se tome y falla la prueba si el estado es no allí, ya que tomó demasiado tiempo de todos modos.

46

Sólo pensé que podría querer una actualización sobre esto ya que la respuesta n. ° 1 en realidad está recomendando un patrón anterior para resolver este problema.

En .NET 4.5 + xUnit 1.9 o superior, puede simplemente devolver una Tarea y opcionalmente usar la palabra clave async de su prueba para que xunit espere a que la prueba se complete de forma asincrónica.

Ver este artículo en xUnit.net 1.9

[Fact] 
public async Task MyAsyncUnitTest() 
{  
    // ... setup code here ...  
    var result = await CallMyAsyncApi(...);  
    // ... assertions here ... 
} 
+0

Ahh ... siempre es bueno cuando hay un apoyo nativo en el marco ... Es bueno saberlo, ¡gracias! –

+1

Tenga en cuenta que es importante devolver una tarea y no está vacía: http://stackoverflow.com/questions/23824660/xunit-async-test-not-working-properly –

+0

Para ser más precisos, el Tipo de devolución del método debe ser Tarea , en realidad no necesitas 'regresar' si estás usando async/await. –

Cuestiones relacionadas