I'm writing unit tests now. I need to simulate long-run method with Mockito to test my implementation's timeout handling. Is it possible with Mockito?
Something like this:
when(mockedService.doSomething(a, b)).thenReturn(c).after(5000L);
I'm writing unit tests now. I need to simulate long-run method with Mockito to test my implementation's timeout handling. Is it possible with Mockito?
Something like this:
when(mockedService.doSomething(a, b)).thenReturn(c).after(5000L);
You could simply put the thread to sleep for the desired time. Watch out tho - such things can really slow down your automated test execution, so you might want to isolate such tests in a separate suite
It would look similar to this:
when(mock.load("a")).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation){
Thread.sleep(5000);
return "ABCD1234";
}
});
I created a utils for this:
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import static org.mockito.Mockito.doAnswer;
public class Stubber {
public static org.mockito.stubbing.Stubber doSleep(Duration timeUnit) {
return doAnswer(invocationOnMock -> {
TimeUnit.MILLISECONDS.sleep(timeUnit.toMillis());
return null;
});
}
public static <E> org.mockito.stubbing.Stubber doSleep(Duration timeUnit, E ret) {
return doAnswer(invocationOnMock -> {
TimeUnit.MILLISECONDS.sleep(timeUnit.toMillis());
return ret;
});
}
}
and in your test case simply use:
doSleep(Duration.ofSeconds(3)).when(mock).method(anyObject());
From mockito 2.8.44, org.mockito.internal.stubbing.answers.AnswersWithDelay is available for this purpose. Here's a sample usage
doAnswer( new AnswersWithDelay( 1000, new Returns("some-return-value")) ).when(myMock).myMockMethod();
Much better for Unit tests is to create method that calls actual Thread.sleep(long l) and then mock that method. With that, you can inject your test with awesome behaviour causing that your test will think it is waiting for as long as you want. With that, you can run a lot of test in blink of the eye and still testing different time-related scenario. Before using this, my UnitTest ran for six minutes. Now its under 200ms.
public class TimeTools {
public long msSince(long msStart) {
return ((System.nanoTime() / 1_000_000) - msStart);
}
public long msNow() {
return (System.nanoTime() / 1_000_000);
}
public Boolean napTime(long msSleep) throws InterruptedException {
Thread.sleep(msSleep);
return true;
}
}
-----------------------------------
@Mock
TimeTools Timetools;
@TEST
public void timeTest() {
when(timeTools.msSince(anyLong()))
.thenReturn(0l)
.thenReturn(5_500l)
.thenReturn(11_000l)
.thenReturn(11_000l)
.thenReturn(0l)
.thenReturn(11_000l)
.thenReturn(11_000l)
.thenReturn(0l)
.thenReturn(29_000l);
}
But best approach is to inject sleeper and then mock it. So in your tests, you won't actually sleep. Then you unit tests will run fast as lightning.