We write unit tests for asynchronous code using MSTest and Moq.
So, we have some code that looks something like this:
var moq = new Mock<Foo>(); moq.Setup(m => m.GetAsync()) .Returns(Task.FromResult(10));
Or as in projects with a later version of Moq
var moq = new Mock<Foo>(); moq.Setup(m => m.GetAsync()) .ReturnsAsync(10);
Looking at the implementation of Moq ReturnsAsync:
public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult>(this IReturns<TMock, Task<TResult>> mock, TResult value) where TMock : class { TaskCompletionSource<TResult> completionSource = new TaskCompletionSource<TResult>(); completionSource.SetResult(value); return mock.Returns(completionSource.Task); }
Both methods seem the same under the hood. Both create a TaskCompletionSource , call SetResult and return a Task
So far so good.
But async short methods are optimized for synchronous action. This seems to mean that the TaskCompletionSource always synchronous, which would also indicate that context processing and any problems associated with this might not happen.
So, if we had some code that executed some async no-no's, such as mixing awaits , Wait() and Result , that these problems would not be detected during unit testing.
Was there any advantage in creating an extension method that always gives you control? Sort of:
public async Task<T> ReturnsYieldingAsync<T>(T result) { await Task.Yield(); return result; }
In this case, we will have a method that is guaranteed to execute asynchronously.
The perceived advantage would be to detect bad asynchronous code. For example, it can catch any deadlock or exception when swallowing during unit testing.
I'm not 100% sure, it is, so I would be interested to know what the community has to say.