1

I have to unit test a method that suspends its execution (does some work periodically):

void m() { do { doSomeWork(); Thread.sleep(1000); } while (condition); } 

What I have to test is multiple while loop execution and check if the doSomeWork() has been done correctly. So currently my test looks like this:

1) start execution of m() in a new thread.

2) in the main thread: Thread.sleep(1000 + 200);

3) in the main thread assert that the work has been done correctly.

4) in the main thread: Thread.sleep(1000 + 200);

5) in the main thread assert that the work has been done correctly.

6) and one more time 4 and 5

The problem is that the doSomeWork() on different machines takes different amount of time and its hard to find a good value to wait in the test.

I have seen a common approach to such situation is to abstract out the sleeping time and in test code don't wait: C# Unit Testing - Thread.Sleep(x) - How to Mock the System Clock

But I really have to verify that the implementation is waiting.

Do you have any suggestions how to write a robust unit test code for such scenario? It can also involve refactoring of the m() method.

2
  • as you mentioned, you would be best to mock the clock, you would want assert that the function hasnt been called before you increment the clock, and then check it has been called after you increment it. Commented Mar 3, 2015 at 20:49
  • any reason you never accepted the answer? Commented Feb 16, 2016 at 15:29

1 Answer 1

2

A common way to handle something like this is to use object wait/notify methods. This will also help make the method m() more usable in other contexts. So something like this implementation:

void m() { do { doSomeWork(); Thread.sleep(1000); synchronized (this) { this.notifyAll(); } } while (condition); } 

Then in your test class you can do:

... synchronized (obj) { obj.wait(10000); } 

The 10000 in the wait is just a timeout to use for the class. This prevents a refactor of m where it sleeps forever (or an equivalent bug) from causing a timeout in your test.

Of course, this suggestion requires some object to use for your mutex. I chose the class itself for m but any object could be used. Sometimes I just create an object just for this type of use: Object mutex = new Object()

If you need to be sure that the work and sleep has succeeded, then you can also use an AtomicInteger as a counter:

AtomicInteger counter = new AtomicInteger(0); void m() { do { doSomeWork(); Thread.sleep(1000); counter.incrementAndGet() synchronized (counter) { counter.notifyAll(); } } while (condition); } 

Then in your test class you can do (proper methods missing for simplicity):

... synchronized (obj.counter) { obj.counter.wait(10000); } assert(obj.counter.get() > 0); 
Sign up to request clarification or add additional context in comments.

5 Comments

This looks interesting. The only problem with this solution I see is that because of the spurious wakeups we should call Object.wait() in a loop and check if the condition until which the wakeup should have happened is true. But in this case this condition is: the doSomeWork() is done and Thread.sleep(1000) is done. But it wouldn't be nice and easy to externalize it.
Actually the main problem is that it doesn't verify that the m() has actually waited for that 1 second. And this is a very important point that I want to verify in this test.
updated to address your concerns. you can go even further and use Semaphore, CountDownLatch, etc from the concurrency package. All depends on really what you need.
Thanks for the update. I also need to somehow verify that the method has really waited after doSomeWork().
insert more counters, etc as needed to check various conditions

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.