Search code examples
c#nunitassertassertion

Evaluate NUnit assertion after a delay


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?


Solution

  • 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.