I am testing code that runs in its own thread in a while loop. The code under test does some stuff based on the current time, then updates an AtomicReference<Integer>
The application logic is an algorithm that runs for days. I need to simulate the behavior by controlling the time readings, and checking the computed results.
I can’t figure out how to mock the time. I provided simplified code examples below.
Code under test
class ClassUnderTest {
private ExecutorService executorService = ...
private MyClock clock;
private AtomicReference<Integer> result = ...
public ClassUnderTest(MyClock clock) {
this.clock = clock;
// start the thread
this.executorService.submit(this::run);
}
public void run() {
while (true) {
if (hasThreeHoursPassed(clock.getTime()) { // <-- PROBLEM, can't mock getTime() from Spock thread
// ... core application logic that requires testing ...
result.set(...);
}
}
}
}
Spock test
def 'test thread' () {
given:
MyClock clockMock = Mock(MyClock)
ClassUnderTest classUnderTest = ClassUnderTest(clockMock)
long mockedTime = 1L;
clockMock.getTime() >> mockedTime
expect:
for (int i = 0; i < 100; i++) {
mockedTime += 1000 * 60 * 60 * 3 // 3 hours
clockMock.getTime() >> mockedTime // <-- PROBLEM, this does not work. The thread does not see this value
classUnderTest.getResult() == ... expected value ...
}
}