Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid Thread.sleep in Unit tests?

Tags:

Let's imagine I have the following method which should be tested:

@Autowired
private RoutingService routingservice;

public void methodToBeTested() {
    Object objectToRoute = initializeObjectToRoute();
    if (someConditions) {
         routingService.routeInOneWay(objectToRoute);
    } else {
         routingService.routeInAnotherWay(objectToRoute);
    }
}

In this case RoutingService is running in the separate thread, thus in it's constructor we have the following:

Thread thread = new Thread(this);
thread.setDaemon(true);
thread.start();

The problem is that RoutingService changes the state of objectToRoute and this is exactly what I want to check, but this doesn't happen straight away thus the test fails. However, if I add Thread.sleep() then it works, but this is bad practice as I know.

How can I avoid Thread.sleep() in this case?

like image 366
Rufi Avatar asked Mar 29 '16 11:03

Rufi


People also ask

How do I stop thread sleep in exams?

You could mock objectToRoute to set the value of a CompletableFuture and then call get on that in your assertion. This will wait until the value is set before continuing. Then set a timeout @Test(timeout=5000) in case the value is never set.

What do you have to avoid in tests in unit testing?

Avoid Test Interdependence You, therefore, cannot count on the test suite or the class that you're testing to maintain state in between tests. But that won't always make itself obvious to you. If you have two tests, for instance, the test runner may happen to execute them in the same order each time.

Why thread sleep is not recommended?

If given a wait of 5000 Milliseconds(5 seconds) and an element just take just 1-2 seconds to load, script will still wait for another 3 seconds which is bad as it is unnecessarily increasing the execution time. So thread. sleep() increases the execution time in cases where elements are loaded in no due time.

What is the alternative for thread sleep in Java?

For example when the threadA need to wait for a certain amount of time you can put the thread in wait state and start a timer task that after a certain amount of time (interval ) call notify and wake up the ThreadA that go ahead, this could be an alternative .


2 Answers

If you are testing [Unit Test] for the method methodToBeTested, you should simply mock routingservice.
You shouldn't be testing any methods that methodToBeTested calls.

However, it sounds like you want to test the RoutingService (you said "The problem is that RoutingService changes the state of objectToRoute and this is exactly what I want to check").

To test RoutingService methods, you should write separate unit tests for those methods.

like image 199
forgivenson Avatar answered Sep 25 '22 13:09

forgivenson


I suggest awaitility for synchronizing asynchronous tests. For example, assume you have an result object that get set after some thread operations and you want to test it. You write statement like this:

 await()
.atMost(100, TimeUnit.SECONDS)
.untilAsserted(() -> assertNotNull(resultObject.getResult()));

It waits maximum 100 seconds, or until the assertion is satisfied. For instance, if getResult() returns something that is not null in between 0-100 seconds, the execution continues unlike Thread.sleep which holds the execution for given time no matter result is there or not.

like image 41
sarah Avatar answered Sep 23 '22 13:09

sarah