使用JUnit/Mockito来确认java.util.Timer.schedule()做了预期的事情?

vhmi4jdf  于 12个月前  发布在  Java
关注(0)|答案(2)|浏览(111)

我已经看到了很多关于JUnit/Mockito中基于时间的测试技术的帖子,但似乎有太多的考虑因素,以至于我对如何看待我自己的测试代码感到困惑-以及我应该如何测试/测试什么。
我的测试代码如下:

class ClassUnderTest {
    Clock clock; // Thought this might be a useful DI, but not sure how...
    String delayString;
    Timer timer;

    public ClassUnderTest(String delayString, Clock clock) {
        this.clock = clock;
        this.delayString = delayString;
        init();
    }

    private void init() {
        ChronoUnit unit = parseDelayStringToGetUnit(); // Implementation not shown here
        Integer amountOfTime = parseDelayStringToGetAmount(); // Implementation not shown here
        long delay = calculateDelay(unit, amountOfTime); // Implementation not show here
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                taskToRun();
            }
        }, delay);
    }

    private void taskToRun() {
        // Does something after a delay
        // Happy to amend signature to take params or return a value ...
    }
}

字符串
它的基本功能在示例化时是调用taskToRun(),但只有在解析了另一个传入的字符串之后才能调用,该字符串可以被转换为ChronoUnit和相关的量。传入的延迟长度可能有限,但范围从15分钟到8小时。
我已经读到我不需要测试计时器本身,但我仍然觉得我的测试方法应该确认taskToRun()最终确实运行,但不是在期望的延迟到期之前。我认为传递java.time.Clock作为依赖注入将有助于基于时间的测试,但目前我不知道如何(在这里),显然它还没有用于任何事情。
我想测试的东西原则上是正确的吗?如果是,我该怎么做?
编辑:
抱歉。刚刚意识到delayString还包括'epochStart',从延迟应该开始开始的时刻。原语'delay'的当前计算将改为计算:
instantWhenDelayExpires = epochStart +(ChronoUnit的数量)
并且定时器然后将使用instantWhenDelayExpires而不是延迟量来调度。
我不认为这特别复杂我的问题,虽然?

uwopmtnx

uwopmtnx1#

但我仍然觉得我的测试方法应该确认taskToRun()最终确实运行,但不是在期望的延迟到期之前
事实上,为了验证这一点,为什么不依赖于指定延迟的Timer.schedule(TimerTask task, long delay)呢?
通过这种方式,您可以在ClassUnderTest中为您的测试添加一个接受Timer的构造函数,并且您可以在单元测试期间模拟它。要AssertTimer做了它设计做的事情,您只需验证mock是用正确的参数调用的,特别是延迟参数。

@Mock
Timer mockedTimer;

@Test
void constructor(){
   long expectedDelay = ...;
   ClassUnderTest objectUnderTest = new ClassUnderTest(..., mockedTimer);
   Mockito.verify(mockedTimer).schedule(Mockito.any(),  expectedDelay);
}

字符串

jv2fixgn

jv2fixgn2#

您可以在应用程序配置中定义bean,

@Bean
public Timer timer()
{
    return new Timer();
}

字符串
自动将bean连接到类中,

@Autowired
private Timer _timer;


在测试课上嘲笑那个豆子

@MockBean
private Timer _timer;


然后,您可以捕获进入计时器的任务,并验证运行任务是否按您的要求运行。

ArgumentCaptor<TimerTask> timerCaptor = ArgumentCaptor.forClass(TimerTask.class);
    Mockito.verify(_timer, Mockito.times(1))
            .scheduleAtFixedRate(timerCaptor.capture(), Mockito.anyLong(), Mockito.anyLong());

    TimerTask timerTask = timerCaptor.getValue();
    Assertions.assertNotNull(timerTask);

    // assuming the time runs the task
    timerTask.run();

    // verify methods inside run task are invoked...

相关问题