I'm trying to write a unit test with NUnit for a method that could take anywhere from 1 to 3 seconds to complete. In order to valid the test all I need to do is check if a List<string> entries
has been incremented in that 1 to 3 second span.
My current solution is to use a Thread.Sleep()
:
1. int currentEntries = entries.count;
2. Call methodA()
3. Thread.Sleep(3000);
4. int updatedEntries = entries.count;
5. Assert.That(updatedEntries, Is.EqualTo(currentEntries+1));
This solution always takes at least 3 seconds, even when methodA() finishes faster.
I have tried using NUnits Delay constraint:
Assert.That(entries.Count, Is.EqualTo(currentEntries+1).After(3).Seconds.PollEvery(250).MilliSeconds);
This would have been ideal, since it supports polling. But the After
constraint is still evaluated instantly instead of after 3 seconds, as discussed here.
Is there a better solution to this issue?
Your call to Assert.That
has an actual argument, which is evaluated immediately before the method is called. The value of entries.Count
is taken and the resulting integer value is copied as the method argument. Within the method, we are dealing with a constant.
When the constraint is re-evaluated every 250 milliseconds, it is done each time against that same copied constant, which of course never changes.
When you use a delayed constraint, with or without polling, the actual argument has to be in the form of a delegate, a lambda or a reference to a field. The following simple modification should make it work.
Assert.That (() => entries.Count, Is.EqualTo(currentEntries+1).After(3).Seconds.PollEvery(250).MilliSeconds);
Alternatively, this should work as well
Assert.That (entries, Has.Count.EqualTo(currentEntries+1).After(3).Seconds.PollEvery(250).Milliseconds);
because the property is evaluated each time we poll.