public async Task CallLongOperation()
{
var result = await _client.LongWebCall();
if (result.Failed)
{
// log failure and exit
}
}
I needed to make sure that the client was invoked just once no matter how many times CallLongOperation gets called – and to make things interesting the client’s method is asynchronous.
Usually when I want to fake a long running call I use WaitHandle but in this case I had something even better…[TestMethod]
public void CallLongOperation_DuringOperationCallAgain_CalledOnlyOnce()
{
var fakeClient = A.Fake<IClient>();
var completionSource = new TaskCompletionSource<Result>();
A.CallTo(() => fakeClient.LongWebCall()).Returns(completionSource.Task);
var cut = new ClassUnderTest(fakeClient);
cut.CallLongOperation();
cut.CallLongOperation();
completionSource.SetResult(new Result());
A.CallTo(() => fakeClient.LongWebCall()).MustHaveHappened(Repeated.Exactly.Once);
}
Using the TaskCompletionSource (line 6) help me simulate an async call that won’t return until I call SetResult on it (line 14) and since I do not muse await on the actual call I write the whole test without creating any additional threads – creating a simple and deterministic unit test.Labels: .NET, async, C#, MSTest, Multi-threading, Unit tests