如何使用 EasyMock、没有 Joda Time 和 PowerMock 将当前系统时间覆盖到 Java 8 Web 应用程序中的特定日期?
How to override current system time to a specific date in a Java 8 web application with EasyMock, without Joda Time, and without PowerMock?
我需要模拟时间(特定 日期,这意味着我可能不会使用 anyLong()
)用于 Java 8 中的测试目的,仅使用 java.time
,因此没有 Joda Time,在 EasyMock 下的测试环境中。
EasyMock 不允许您模拟像 LocalDateTime.now()
这样的静态方法。 PowerMock 可以,但不允许我使用 PowerMock。
Joda Time 库提供了一种巧妙而优雅的方式来模拟时间 DateTimeUtils.setCurrentMillisFixed()
,DateTimeUtils.setCurrentMillisSystem()
回到现在。
只有我不允许使用 Joda Time。
有人告诉我使用模拟时钟 java.time.Clock
class 实例并将其注入 LocalDateTime.now()
,如下所示:LocalDateTime.now(mockClock)
有没有办法在没有 Joda Time 的情况下 正确地实现它并且
没有 PowerMock?
正好有办法。这是您需要做的:
测试需要做的事情class
步骤 1
向测试的 class 添加一个新的 java.time.Clock
属性 MyService
并确保使用实例化块或构造函数将新属性正确初始化为默认值:
import java.time.Clock;
import java.time.LocalDateTime;
public class MyService {
// (...)
private Clock clock;
public Clock getClock() { return clock; }
public void setClock(Clock newClock) { clock = newClock; }
public void initDefaultClock() {
setClock(
Clock.system(
Clock.systemDefaultZone().getZone()
// You can just as well use
// java.util.TimeZone.getDefault().toZoneId() instead
)
);
}
{
initDefaultClock(); // initialisation in an instantiation block, but
// it can be done in a constructor just as well
}
// (...)
}
第 2 步
将新属性 clock
注入到调用当前日期时间的方法中。例如,在我的例子中,我必须检查数据库中存储的日期是否发生在 LocalDateTime.now()
之前,我将其替换为 LocalDateTime.now(clock)
,如下所示:
import java.time.Clock;
import java.time.LocalDateTime;
public class MyService {
// (...)
protected void doExecute() {
LocalDateTime dateToBeCompared = someLogic.whichReturns().aDate().fromDB();
while (dateToBeCompared.isBefore(LocalDateTime.now(clock))) {
someOtherLogic();
}
}
// (...)
}
考试需要做的事情class
步骤 3
在测试 class 中,创建一个模拟时钟对象并在调用测试方法 doExecute()
之前将其注入到测试 class 的实例中,然后将其重置紧接着,像这样:
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import org.junit.Test;
public class MyServiceTest {
// (...)
private int year = 2017; // Be this a specific
private int month = 2; // date we need
private int day = 3; // to simulate.
@Test
public void doExecuteTest() throws Exception {
// (...) EasyMock stuff like mock(..), expect(..), replay(..) and whatnot
MyService myService = new MyService();
Clock mockClock =
Clock.fixed(
LocalDateTime.of(year, month, day, 0, 0).toInstant(OffsetDateTime.now().getOffset()),
Clock.systemDefaultZone().getZone() // or java.util.TimeZone.getDefault().toZoneId()
);
myService.setClock(mockClock); // set it before calling the tested method
myService.doExecute(); // calling tested method
myService.initDefaultClock(); // reset the clock to default right afterwards with our own previously created method
// (...) remaining EasyMock stuff: verify(..) and assertEquals(..)
}
}
在调试模式下检查,你会看到 2017 Feb 3 的日期已正确注入 myService
实例并用于比较指令,然后已正确重置为当前日期 initDefaultClock()
.
我需要模拟时间(特定 日期,这意味着我可能不会使用 anyLong()
)用于 Java 8 中的测试目的,仅使用 java.time
,因此没有 Joda Time,在 EasyMock 下的测试环境中。
EasyMock 不允许您模拟像 LocalDateTime.now()
这样的静态方法。 PowerMock 可以,但不允许我使用 PowerMock。
Joda Time 库提供了一种巧妙而优雅的方式来模拟时间 DateTimeUtils.setCurrentMillisFixed()
,DateTimeUtils.setCurrentMillisSystem()
回到现在。
只有我不允许使用 Joda Time。
有人告诉我使用模拟时钟 java.time.Clock
class 实例并将其注入 LocalDateTime.now()
,如下所示:LocalDateTime.now(mockClock)
有没有办法在没有 Joda Time 的情况下 正确地实现它并且 没有 PowerMock?
正好有办法。这是您需要做的:
测试需要做的事情class
步骤 1
向测试的 class 添加一个新的 java.time.Clock
属性 MyService
并确保使用实例化块或构造函数将新属性正确初始化为默认值:
import java.time.Clock;
import java.time.LocalDateTime;
public class MyService {
// (...)
private Clock clock;
public Clock getClock() { return clock; }
public void setClock(Clock newClock) { clock = newClock; }
public void initDefaultClock() {
setClock(
Clock.system(
Clock.systemDefaultZone().getZone()
// You can just as well use
// java.util.TimeZone.getDefault().toZoneId() instead
)
);
}
{
initDefaultClock(); // initialisation in an instantiation block, but
// it can be done in a constructor just as well
}
// (...)
}
第 2 步
将新属性 clock
注入到调用当前日期时间的方法中。例如,在我的例子中,我必须检查数据库中存储的日期是否发生在 LocalDateTime.now()
之前,我将其替换为 LocalDateTime.now(clock)
,如下所示:
import java.time.Clock;
import java.time.LocalDateTime;
public class MyService {
// (...)
protected void doExecute() {
LocalDateTime dateToBeCompared = someLogic.whichReturns().aDate().fromDB();
while (dateToBeCompared.isBefore(LocalDateTime.now(clock))) {
someOtherLogic();
}
}
// (...)
}
考试需要做的事情class
步骤 3
在测试 class 中,创建一个模拟时钟对象并在调用测试方法 doExecute()
之前将其注入到测试 class 的实例中,然后将其重置紧接着,像这样:
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import org.junit.Test;
public class MyServiceTest {
// (...)
private int year = 2017; // Be this a specific
private int month = 2; // date we need
private int day = 3; // to simulate.
@Test
public void doExecuteTest() throws Exception {
// (...) EasyMock stuff like mock(..), expect(..), replay(..) and whatnot
MyService myService = new MyService();
Clock mockClock =
Clock.fixed(
LocalDateTime.of(year, month, day, 0, 0).toInstant(OffsetDateTime.now().getOffset()),
Clock.systemDefaultZone().getZone() // or java.util.TimeZone.getDefault().toZoneId()
);
myService.setClock(mockClock); // set it before calling the tested method
myService.doExecute(); // calling tested method
myService.initDefaultClock(); // reset the clock to default right afterwards with our own previously created method
// (...) remaining EasyMock stuff: verify(..) and assertEquals(..)
}
}
在调试模式下检查,你会看到 2017 Feb 3 的日期已正确注入 myService
实例并用于比较指令,然后已正确重置为当前日期 initDefaultClock()
.