Can I delay a stubbed method response with Mockito?

JavaJunitMockingMockito

Java Problem Overview


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);

Java Solutions


Solution 1 - Java

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";
   }
});

Solution 2 - Java

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();

Solution 3 - Java

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());

Solution 4 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser961548View Question on Stackoverflow
Solution 1 - JavaK.L.View Answer on Stackoverflow
Solution 2 - JavaViswanathView Answer on Stackoverflow
Solution 3 - JavaSimon LudwigView Answer on Stackoverflow
Solution 4 - JavaMatej LachmanView Answer on Stackoverflow