Is unit testing of interval actions with Thread.Sleep bad?

If I have a test object with a timer that triggers some action in a given interval, what is a good way to test this?

One method is to wrap the timer in the interface and enter it as a dependency.

However, I would like to avoid creating another abstraction. It seems I can avoid this by introducing an update interval rather than a timer. Then in my test (assuming type AAA testing) I put a Thread.Sleep after Act and before Assert, using a very small time value, so the test will not take much time.

It is a bad idea? I know that this probably does not fully comply with the principles of TDD, but it seems that there should be a line where you stop everything in a row with the contract and enter it.

+7
source share
2 answers

If the amount you sleep does not matter for the test, and you can set me to 1 millisecond, then it should be good to just sleep for 1 millisecond in your test.

However, if you want to test complex temporal behavior with timeouts and specific actions taken at specific points in time, it quickly becomes easier to abstract from the concept of time and introduce it as a dependency. Then your tests can run in virtual time and run without delay, even if the code works as if it were passing in real time.

An easy way to virtualize time is to use something like this:

 interface ITimeService { DateTime Now { get; } void Sleep(TimeSpan delay); } class TimeService : ITimeService { public DateTime Now { get { return DateTime.UtcNow; } } public void Sleep(TimeSpan delay) { Thread.Sleep(delay); } } class TimeServiceStub : ITimeService { DateTime now; public TimeServiceStub() { this.now = DateTime.UtcNow; } public DateTime Now { get { return this.now; } } public void Sleep(TimeSpan delay) { this.now += delay; } } 

You will need to expand on this idea if you need more reactive behavior, such as triggering timers, etc.

+5
source

Injection injection is a way to completely eliminate the presence of "test" code in your production code (for example, setting the interval for unit testing only).

However, in this case, I would use the code for a given interval, but use it both in unit tests and in production. Did you arrange production for anything, and unit tests installed it in a very small amount (10 ms?). Then you will not have any dead code hanging in production.

If you set the interval, I don’t understand why you need Thread.Sleep? Just make your unit test block until you receive an event from the subject (or continuously polling the object). Whatever method you use.

+2
source

All Articles