Reputation: 6772
In our Web API integration tests we are having issues with testing the async actions.
In my simple test I created a simple controller action:
[HttpGet]
[Route("test")]
public async Task<ApiResponse> Test()
{
return await Task.FromResult(new ApiResponse(true));
}
However when I am running the integration tests it fails on the following exception:
System.InvalidCastException : Unable to cast object of type 'Jacobo.Api.Model.Shared.ApiModels.ApiResponse' to type 'System.Threading.Tasks.Task`1[Jacobo.Api.Model.Shared.ApiModels.ApiResponse]'. at Castle.Proxies.IIdentityControllerProxy.Test() at ServerApi.IntegrationTests.IdentityControllerTests.d__10.MoveNext() in E:\Dev\Jacobo\ServerApi.IntegrationTests\IdentityControllerTests.cs:line 218 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at NUnit.Framework.Internal.AsyncInvocationRegion.AsyncTaskInvocationRegion.WaitForPendingOperationsToComplete(Object invocationResult) at NUnit.Framework.Internal.Commands.TestMethodCommand.RunAsyncTestMethod(TestExecutionContext context)
I can see where this is coming from as we are returning a result which is no longer matching the action return type which is obviously wrapped in a task.
The whole block of our Interceptor code runs fine:
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.
}
and then the test fails as it's trying to return the awaited result:
[Test]
public async Task GettingAsyncActionResultWillSucceed()
{
var ctl = BuildController(new SameMethodStack("GET"));
var result = await ctl.Test();
Assert.IsTrue(result.Success);
}
I am very unsure where to go from here.
Upvotes: 2
Views: 247
Reputation: 6772
Finally found a solution. I had to detect if the method is async and based on that wrap the result into a task:
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 });
}
Upvotes: 1