Add ability for asynchronously waiting for an invocation
Some asynchronous code, like the ones involving channels, are hard to test, because writing to a channel starts background tasks on the thread pool that are expected to complete eventually, but are impossible to await. Similar problems arise when using the Rx.NET library, where observables might dispatch their updates asynchronously. Adding delays in tests can increase build times significantly when the project is large. I will use the below testing code as an example:
var subscriber = Mock.Of<IAsyncObserver<string>>();
await topic.SubscribeAsync(subscriber); // topic is the system under test
await topic.PublishAsync("test");
Mock.Get(subscriber).Verify(_ => _.OnNextAsync("test"));
This test will be inherently flaky if the system under test is dispatching messages using a Channel<string> or any other asynchronous mechanism where calling the subscriber is done in a background task. What we would need here is the ability to asynchronously wait for the invocation within some defined timeout:
var subscriber = Mock.Of<IAsyncObserver<string>>();
await topic.SubscribeAsync(subscriber); // topic is the system under test
await topic.PublishAsync("test");
await Mock.Get(subscriber).WaitAsync(_ => _.OnNextAsync("test"), TimeSpan.FromSeconds(10));
This task should only throw if the specified invocation did not happen within the provided timespan.
Alternatively, if Mock.GetMatchingInvocationCount was public, or there was some public matching method on IInvocation itself, we could write our own utilities like the above WaitAsync method.
Due to lack of recent activity, this issue has been labeled as 'stale'. It will be closed if no further activity occurs within 30 more days. Any new comment will remove the label.
Hi there. Yes, the lack of a public API for consuming matchers against invocations are a limitation of the current approach. This should be addressed in a future Moq.
Due to lack of recent activity, this issue has been labeled as 'stale'. It will be closed if no further activity occurs within 30 more days. Any new comment will remove the label.
This issue will now be closed since it has been labeled 'stale' without activity for 30 days.
