-
-
Notifications
You must be signed in to change notification settings - Fork 798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to evaluate "verify" after a certain period of time #931
Comments
I don't think so. To me it seems like a bad idea (in general) to introduce time dependencies into tests, unless you really have to. I'm saying that because you usually get no guarantees from the OS nor from the test runner how your test is scheduled for execution. For example, it could be that it gets run on a low-priority thread with lots of interruptions, and will therefore take longer than you expect. If you choose a timeout that's too small, you'll end up with a fragile test that sometimes fails for no good reason. The easiest way to prevent that will be to choose a timeout that's too large, making your test run unnecessarily slow. I believe that tests should be written in a time-independent manner whenever possible, and Moq's API should reflect that. I dare say it's only in a small minority of all tests that time matters. For these, like you say, it would be simple enough to have an |
@stakx: A example from a other mock framework: https://www.javadoc.io/doc/org.mockito/mockito-core/2.2.9/org/mockito/verification/VerificationWithTimeout.html |
@bormm: Yes, there may possibly be some cases where you really do want a timeout in your test. I still think this should be the exception, rather than the general case. And like I said, in those few cases, nothing stops you from simply putting an |
P.S.: The only thing that might make this feature slightly more attractive would be if |
@stakx Exactly. As I wrote, your suggested "Task.Delay(timeout);" will delay the test in any case. Of course often timeouts are too large or too small. Its always some compromise. But what I more dislike is to add fixed sleeps in the code. In regular code its a absolute no-no. It shouldn't be needed to simulate testing some timing condition. So it would be very good if Moq provides some mechanism that allows to verify that something happens in at least some time, but does not wait always for that time. |
I see. I am still wondering whether this needs to be in the core library... my gut feeling still objects to it. This might easily get overused and lead more novice users down a wrong path. It should be possible to implement most of this capability in client code, or offer it in a contrib NuGet package. As a possible starting point, a naive implementation might look as follows: async static Task Verify<T>(this Mock<T> mock, ..., TimeSpan timeout)
{
const int GRANULARITY = 50;
int elapsed = 0;
while (elapsed < timeout.TotalMilliseconds)
{
try
{
mock.Verify(...);
return;
}
catch
{
// perhaps collect all exceptions here, to be re-thrown after a timeout
await Task.Delay(GRANULARITY);
elapsed += GRANULARITY;
}
}
throw new Exception("Timeout during verification");
} Granted, that's a bit ugly, and not entirely correct semantically since |
To be realistic: This request had no comment for 2 years.
Anyway, it seems not very urgent and resources are always low. |
I created a extension class and put it here. Works good for me and allows doing things like that:
Any additional hint is welcome. |
I have the same problem. I know there are workarounds. Additionally to the general wait suggested above one could use a Setup().Callback() and set a TaskCompletionSource in the callback. The test can than wait for this TaskCompletionSource with a timeout. But this is really cumbersome. The timeout for verify like suggested in the extension from @bormm would be great to have in Moq itself. There is a reason why it was added to Mockito. In a world of distributed services it is quite normal to have such timeouts. |
To the point about others not having this need, FYI that I very much need it. I have a bunch of Task.Delay() calls in my tests. They'd be faster with a mechanism like what you describe. I implemented my own for now client-side. It'd be a great addition as part of Moq. |
Would this enhancement align with the roadmap of moq?
Sometimes we need to verify a call to a method but need to consider timings introduced by the implementation.
A modified example from the docs how it could look like
mock.Verify(foo => foo.DoSomething("ping"),After(2000,100), Times.AtLeast(2));
This would verify that a call to
DoSomething
was done at least twice within the period of 2 seconds. To avoid blocking the code longer than necessary and because this could be implemented as anThread.Sleep(2000);
before the verify, the second parameter is the time interval in which the verification is evaluated. If condition is true after 200 ms, it completes earlier.The text was updated successfully, but these errors were encountered: