我可以用Mockito延迟存根方法响应吗?

v2g6jxz6  于 2022-11-08  发布在  其他
关注(0)|答案(5)|浏览(168)

我现在正在写单元测试。我需要用Mockito模拟长时间运行的方法来测试我的实现的超时处理。用Mockito可以吗?
大概是这样的:

when(mockedService.doSomething(a, b)).thenReturn(c).after(5000L);
xmakbtuz

xmakbtuz1#

您可以简单地让线程休眠所需的时间。注意--这样的事情确实会降低自动化测试的执行速度,所以您可能希望将这样的测试隔离在一个单独的套件中
它看起来类似于:

when(mock.load("a")).thenAnswer(new Answer<String>() {
   @Override
   public String answer(InvocationOnMock invocation){
     Thread.sleep(5000);
     return "ABCD1234";
   }
});
fkaflof6

fkaflof62#

从mockito 2.8.44开始,org.mockito.internal.stubbing. answers.AnswersWithDelay可用于此目的。

doAnswer( new AnswersWithDelay( 1000,  new Returns("some-return-value")) ).when(myMock).myMockMethod();
kuhbmx9i

kuhbmx9i3#

我为此创建了一个utils:

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

}

在测试用例中只需使用:

doSleep(Duration.ofSeconds(3)).when(mock).method(anyObject());
sycxhyv7

sycxhyv74#

when(mock.mockmethod(any)).delegate.thenAnswer(
new AnswersWithDelay(
 10000000, // nanosecond
 new Returns(
     Future.Successful(Right()),
 ),

mockito-scala我用mockitoScala插件实现了它。它已经过测试,可以在指定时间休眠

q35jwt9p

q35jwt9p5#

对于单元测试更好的方法是创建调用实际Thread的方法。sleep(long l),然后模仿这个方法。这样,你就可以给你的测试注入令人敬畏的行为,使你的测试认为它在等待你想要的时间。这样,你就可以在眨眼之间运行很多测试,并且仍然测试不同的时间相关的场景。在使用这个之前,我的单元测试运行了六分钟。现在它不到200毫秒。

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

但是最好的方法是注入睡眠者,然后模拟它,这样在你的测试中,你实际上不会睡觉,这样你的单元测试就会像 lightning 一样快速运行。

相关问题