2

Dans nos tests d'intégration de l'API Web, nous rencontrons des problèmes pour tester les actions asynchrones.Web API - Interceptor - Interception des actions du contrôleur asynchrone

Dans mon test simple j'ai créé une action simple contrôleur:

[HttpGet] 
[Route("test")] 
public async Task<ApiResponse> Test() 
{ 
    return await Task.FromResult(new ApiResponse(true)); 
} 

Cependant, quand je courais les tests d'intégration, il ne parvient à l'exception suivante:

System.InvalidCastException: Impossible de jeter objet de type 'MoovShack.Api.Model.Shared.ApiModels.ApiResponse' à type 'System.Threading.Tasks.Task`1 [MoovShack.Api.Model.Shared.ApiModels.ApiResponse]'. à Castle.Proxies.IIdentityControllerProxy.Test() à ServerApi.IntegrationTests.IdentityControllerTests.d__10.MoveNext() dans E: \ Dev \ moovshack \ ServerApi.IntegrationTests \ IdentityControllerTests.cs: ligne 218 --- Fin de trace de la pile à partir de l'emplacement précédent où --- exception a été levée à System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() à NUnit.Framework.Internal.AsyncInvocationRegion.AsyncTaskInvocationRegion.WaitForPendingOperationsToComplete (Object invocationResult) à NUnit.Framework. Internal.Commands.TestMethodCommand.RunAsyncTestMethod (TestExecutionContext contexte)

Je peux voir d'où cela vient car nous retournons un résultat qui ne correspond plus au type de retour d'action qui est évidemment enveloppé dans une tâche.

Le bloc entier de notre code Interceptor fonctionne très bien:

public void Intercept(IInvocation invocation) 
{ 
    // our interceptor implementation ... 
    // some irrelevant code before this 
    invocation.ReturnValue = webInvocation.Invoke(_client, invocation.Arguments); // the return value is populated correctly. not wrapped in a task. 
} 

puis échoue le test car il essaie de retourner le résultat attendu:

[Test] 
public async Task GettingAsyncActionResultWillSucceed() 
{ 
    var ctl = BuildController(new SameMethodStack("GET")); 
    var result = await ctl.Test(); 
    Assert.IsTrue(result.Success); 
} 

Je suis très sûr où aller à partir ici.

Répondre

1

Enfin trouvé une solution. J'ai dû détecter si la méthode est asynchrone et basée sur celle-ci envelopper le résultat dans une tâche:

if (isAsync) 
      { 
       var result = webInvocation.Invoke(_client, invocation.Arguments); 
       var type = result.GetType(); 
       var methodInfo = typeof(Task).GetMethod("FromResult"); 
       var genericMethod = methodInfo.MakeGenericMethod(type); 
       invocation.ReturnValue = genericMethod.Invoke(result, new []{ result }); 
      }