模拟Instant.now()而不将时钟释放到构造函数中或没有时钟对象

时间:2019-03-21 20:58:50

标签: java junit java-8

我的一种方法中有以下代码-

ZonedDateTime current = Instant.now().atZone(ZoneId.of(AMERICA_NEW_YORK));

我想在junit测试中模拟current

我尝试使用java.time.Clock,但是为此我需要将其添加到类构造函数中,因为我的代码被写入到Spring的旧版本中,并且使用基于xml的配置,该类会引起问题,因为它需要在应用程序上下文中使用构造函数参数.xml文件(如果我将构造函数与Clock一起使用)。

有什么方法可以避免在上面的代码中配置构造函数并模拟current

更新

根据帕维尔·斯米尔诺夫(Pavel Smirnov)的评论,我在下面进行了尝试,但是current仍返回今天的日期,而不是我嘲笑的日期。

ZonedDateTime exactOneDay = ZonedDateTime.parse("Sun Oct 21 12:30:00 EDT  2018", Parser); 
    doReturn(exactOneDay).when(spyEmployeeHelper).getCurrentTime();
    employee = getEmployees().get(0);
    assertEquals(Integer.valueOf(1), employee.getNoticePeriod());

2 个答案:

答案 0 :(得分:2)

您可以声明一个返回ZoneDateTime的函数:

public ZoneDateTime getCurrentTime () {
    return Instant.now().atZone(ZoneId.of(AMERICA_NEW_YORK));
}

并将该函数的结果分配给current字段:

ZonedDateTime current = getCurrentTime();

现在,您可以使用Mockito framework将其替换为所需的值:

doReturn(yourValue).when(yourObject).getCurrentTime();

答案 1 :(得分:1)

使用 Mockito 时,您可以像这样轻松模拟:

    ZoneId zoneId = ZoneId.of("America/New_York");
    ZonedDateTime current = ZonedDateTime.now(zoneId);
    Timestamp timestamp = Timestamp.from(Instant.now());
   
    when(timestamp.toInstant()).thenReturn(Instant.from(current));

添加超时测试示例:

@Test
public void testForTimeout() throws InterruptedException {

    ZoneId zoneId = ZoneId.of("America/New_York");
    ZonedDateTime current = ZonedDateTime.now(zoneId);
    Timestamp timestampBeforeCall = Timestamp.from(Instant.now());

    // Call Class.method() or here instead we just introduce an artificial wait time :
    Thread.sleep(3000);

    Timestamp timestampAfterCall = Timestamp.from(Instant.now());
    long timeoutInMilliseconds = 2000;
    long diff = timestampAfterCall.getTime() - timestampBeforeCall.getTime();
    log.info(String.valueOf(diff));
    if(diff > timeoutInMilliseconds) {
        log.error("Call Timed Out!");
    }
}