Testing code which uses ScheduledExecutorService (without using Sleep) Testing code which uses ScheduledExecutorService (without using Sleep) multithreading multithreading

Testing code which uses ScheduledExecutorService (without using Sleep)


Your "unit tests" sound a little bit like integration tests. You are not only testing the unit that uses the ScheduledExecutorService, but you are also testing the ScheduledExecutorService itself.

A better approach would be to inject a mock ScheduledExecutorService. In other words, you shouldn't need to test that the timed event actually happens four seconds later; you should only need to test that your unit asked the scheduler to run it four seconds later.

That's where mocks come in. You inject the mock scheduler, perform some operation on your unit that should cause it to interact with the scheduler, and then you can interrogate the mock to verify that the interaction actually happened in the expected way.

If you do it right, each test case can complete in milliseconds or maybe microseconds instead of seconds.


I have found, that DeterministicScheduler (from jMock lib) is the nice way to test code, which uses ScheduledExecutorService.

It provides similar functionality like TestScheduler provides for code, which uses RxJava or DelayController for Kotlin code, which uses coroutine.

In both cases tick() does exactly the same as advanceTimeBy() is doing in earlier mentioning libs:it moves virtual time forward and runs any task, which is expected to be executed within given time frame.

You would need to add core jMock lib in order to use it.

E.g. using Gradle:

dependencies {    //Used only as provider of DeterministicScheduler (test implementation of ScheduledExecutorService)    testImplementation("org.jmock:jmock:2.12.0")}

Off topic: as far as I can see it's general purouse functionality, which is not related to jMock mocking functionality.Ideally it would be nice to provide it as a separate JAR/maven artifact so that people can easily pull it without adding whole jmock lib.I have crated an issue with this suggestion already.


It's surprisingly tough to make ScheduleExecutorService itself testable. Frustratingly its implementation (ScheduledThreadPoolExecutor) does have a now() method. In principle you could override this and control the time! The problem is that the method is package-private and final, so it's not available to be overridden. It might be possible to override this using something like PowerMock.

If you can't override this method then there's not really much of ScheduleExecutorService you can use. In principle you could implement your own subclass of ThreadPoolExecutor that honours the ScheduledExectuorService but that involves implementing a custom BlockingQueue which is quite a complicated thing to get right.

The simplest thing is to use a Mock implementation of ScheduleExecturoService - there is an (incomplete) example that does exactly this on the Mockito Wiki.