I have the following code which i'd like to test:
private Task _keepAliveTask; // get's assigned by object initializer
public async Task EndSession()
{
_cancellationTokenSource.Cancel(); // cancels the _keepAliveTask
await _logOutCommand.LogOutIfPossible();
await _keepAliveTask;
}
It is important that the EndSession
Task only ends once the `_keepAliveTask' ended. However, i'm struggling to find a way to test it reliably.
non-async
method
If there wouldn't be the call to _logOutCommand.LogOutIfPossible() it would be quite simple: i'd just remove the async
and return _keepAliveTask
instead of await
ing it:
public Task EndSession()
{
_cancellationTokenSource.Cancel();
return _keepAliveTask;
}
non-async method, sync over async
Of course, i could do something similar:
public Task EndSession()
{
_cancellationTokenSource.Cancel(); // cancels the _keepAliveTask
_logOutCommand.LogOutIfPossible().Wait();
return _keepAliveTask;
}
But that is a no-go (sync over async).
observing effects instead of verifying calls
Now of course instead of "unit" testing method calls etc. i could always observe effects. Which is: As long as _keepAliveTask
hasn't ended the EndSession
Task
mustn't end either. But since i can't wait indefinite one has to settle for a timeout. The tests should be fast so a timeout like 5 seconds is a no go. So what i've done is:
[Test]
public void EndSession_MustWaitForKeepAliveTaskToEnd()
{
var keepAlive = new TaskCompletionSource<bool>();
_cancelableLoopingTaskFactory
.Setup(x => x.Start(It.IsAny<ICancelableLoopStep>(), It.IsAny<CancellationToken>()))
.Returns(keepAlive.Task);
_testee.StartSendingKeepAlive();
_testee.EndSession()
.Wait(TimeSpan.FromMilliseconds(20))
.Should().BeFalse();
}
But i really really dislike this approach. It's hard to understand and it's unreliable.
So is there any reliable way to verify that an async
method is await
ing a task?
Aucun commentaire:
Enregistrer un commentaire