I have a class that basically has this code:
public class ManagerClass {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
void methodIWantToTest(/* params */){
try {
executor.execute(() -> {
privateMethodINeedToWaitFor(/* params */);
// Other stuff
})
} // catch
}
}
I need to test this method (methodIWantToTest
), and at the moment the assertion runs before privateMethodINeedToWaitFor
has finished.
I don't know enough about threading to know if there's any way for me to wait for methodIWantToTest
and every thread created within that method. The privateMethodIHaveToWaitFor
updates some values that I need to check in my assertion.
I'm not comfortable refactoring this code yet as I'm not familiar enough with the codebase, so I would rather apply a solution on the test for the time being.
Currently on my test I do
managerClass.methodIWantToTest(/* params */).
Thread.sleep(1000);
List<Things> list = managerClass.getListOfThings();
assertEquals(1, list.size());
// more assertions
which works as a way to check my test passes in my local environment, the sleep() seems enough. However I'd like my code to wait for the actual threads to be done, not just have an arbitrary sleep time.
You can use the awaitility library, which allows for constructs like
await()
.atMost(30, SECONDS)
.until(() -> managerClass.getListOfThings().size() == 1);
It will check the condition every 500 ms (adjustable default) and fail after the given at most time if not fulfilled.
One might argue it's syntactic sugar for something like
try {
Instant latestEndTime = Instant.now().plusSeconds(30);
boolean ok = managerClass.getListOfThings().size() == 1;
while (!ok) {
if (Instant.now().isAfter(latestEndTime)) {
fail("condition not fulfilled after 30 seconds");
}
Thread.sleep(500);
ok = managerClass.getListOfThings().size() == 1;
}
} catch (InterruptedException x) { // Thread.sleep() throws this
fail("uh-oh - " + x);
}