2012-08-22 9 views
25

Estoy trabajando para convertir un cuerpo de código asp.net sincrónico en .NET 4.5 y la nueva sintaxis asíncrona.Conversión de simulaciones de Moq sincrónicas en async

tengo una gran cantidad de código de prueba que se parece a:

var retVal = new Foo(bar,baz); 
_myMock.Setup(x => x.DoSomething(123)).Returns(retVal); 

al convertir la firma de HacerAlgo de Foo DoSomething() a async Task<Foo> DoSomething(), toda mi código de prueba tiene que ser reescrito. Mi solución actual es la de convertir el código original a algo como:

var retVal = new Foo(bar,baz); 
_myMock.Setup(x => x.DoSomething(123)) 
    .Returns(new Task<Foo>(()=>retVal)); 

Esto no es un particular transformar duro, pero es tedioso cuando tengo miles de pruebas que necesitan ser actualizados.

Intenté hacer un método de extensión llamado ReturnsAsync para hacer algo de esa forma m, pero estaba teniendo algunos problemas de tipo inferrence que no pude precisar. ¿Existe una forma estándar o más sencilla de convertir este tipo de simulacro para manejar mejor el método asincrónico?

Respuesta

20

Moq 4.2 añade un método ReturnsAsync() extensión, por lo que ya no tendrá que añadir su propia.

34

En primer lugar, nombrando: El Patrón asincrónico basado en tareas (TAP) dice que todos los métodos que son asincrónicos y devuelven Task s deben nombrarse con Async. Por lo tanto, su método debe llamarse DoSomethingAsync.

En segundo lugar, el constructor de Task crea un Task que no se inicia, usted tiene que Start() manualmente. Si su método actual DoSomething hace esto también, eso nuevamente no sigue a TAP y significa que su código no funcionará bien con await. En su lugar, debe usar Task.Run(() => value) o, mejor aún, Task.FromResult(value).

En tercer lugar, sería mejor si nos mostrara su código que no funcionó bien, para que podamos decirle dónde cometió un error.

Ahora, el cuerpo del método de extensión ReturnsAsync() es bastante simple, pero la mayor parte del trabajo para mí fue en averiguar los tipos correctos (especialmente porque no conozco Moq). El código es el siguiente:

public static class MoqExtensions 
{ 
    public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult>(
     this IReturns<TMock, Task<TResult>> setup, TResult value) 
     where TMock : class 
    { 
     return setup.Returns(Task.FromResult(value)); 
    } 
}