Junit 如何使用EasyMock、Joda time和PowerMock将当前系统时间覆盖到Java 8 web应用程序中的特定日期?
我需要在EasyMock下的测试环境中,在Java 8中单独使用Junit 如何使用EasyMock、Joda time和PowerMock将当前系统时间覆盖到Java 8 web应用程序中的特定日期?,junit,java-8,junit4,easymock,java-time,Junit,Java 8,Junit4,Easymock,Java Time,我需要在EasyMock下的测试环境中,在Java 8中单独使用Java.time(因此没有Joda time),模拟时间(到特定的日期,这意味着我不能使用anyLong())进行测试 EasyMock不允许您模拟静态方法,如LocalDateTime.now()。PowerMock有,但我不允许使用PowerMock Joda时间库提供了一种简洁而优雅的模拟时间的方法,它使用DateTimeUtils.setCurrentMillisFixed()和DateTimeUtils.setCurre
Java.time
(因此没有Joda time),模拟时间(到特定的日期,这意味着我不能使用anyLong()
)进行测试
EasyMock不允许您模拟静态方法,如LocalDateTime.now()
。PowerMock有,但我不允许使用PowerMock
Joda时间库提供了一种简洁而优雅的模拟时间的方法,它使用DateTimeUtils.setCurrentMillisFixed()
和DateTimeUtils.setCurrentMillisSystem()
返回当前时刻
只是我不允许利用乔达的时间
我被告知使用模拟时钟java.time.clock
类实例并将其注入LocalDateTime.now()
如下:LocalDateTime.now(模拟时钟)
有没有一种方法可以在没有Joda Time的情况下正确地执行它
没有PowerMock?这是有办法的。以下是您需要做的: 在测试的课堂上需要做什么 第一步 将新的
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();
}
}
// (...)
}
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(..)
}
}
在测试课上需要做什么
步骤3
在测试类中,在调用测试方法doExecute()
之前,创建一个模拟时钟对象并将其注入到测试类的实例中,然后立即重置它,如下所示:
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();
}
}
// (...)
}
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年2月3日的日期已正确注入
myService
实例并在比较指令中使用,然后已使用initDefaultClock()
正确重置为当前日期亲爱的同事们,请随意评论或完成我的回复。很好!只是一些细节:Clock.system(Clock.systemDefaultZone().getZone())
是多余的,您只需使用Clock.systemDefaultZone()
——要获得系统默认时区,只需使用ZoneId.systemDefaultZone()
(与Clock.systemDefaultZone().getZone()相同)
和java.util.TimeZone.getDefault().toZoneId()
)-只要小心。如果在doExecute
之后不使用myService
(或者如果只用于不使用Clock
的东西),就不需要调用initDefaultClock
。实际上,我更喜欢使MyService
不可变(无设置器),并创建两个构造函数:一个没有参数将时钟设置为clock.systemDefaultZone()
,另一个接收时钟-但现在我正在输入设计细节,可能超出了可测试性的范围。