gpt4 book ai didi

java - Mockito:如何模拟 JodaTime 的界面

转载 作者:搜寻专家 更新时间:2023-10-30 21:30:11 24 4
gpt4 key购买 nike

我使用 JodaTime#DateTime,我需要模拟它的行为。由于无法直接模拟 JodaTime#DateTime,因此我创建了一个接口(interface)

时钟.java

public interface Clock {
DateTime getCurrentDateTimeEST();
DateTime getFourPM_EST();
DateTime getSevenPM_EST();
}

JodaTime.java

public class JodaTime implements Clock {

@Override
public DateTime getCurrentDateTimeEST() {
return new DateTime(DateTimeZone.forID("EST"));
}

@Override
public DateTime getFourPM_EST() {
DateTime current = getCurrentDateTimeEST();
return new DateTime(current.getYear(), current.getMonthOfYear(),
current.getDayOfMonth(), 16, 0, 0, 0, DateTimeZone.forID("EST"));
}

@Override
public DateTime getSevenPM_EST() {
DateTime current = getCurrentDateTimeEST();
return new DateTime(current.getYear(), current.getMonthOfYear(),
current.getDayOfMonth(), 19, 0, 0, 0, DateTimeZone.forID("EST"));
}
}

这是我要测试的方法

public class PrintProcessor{

Clock jodaTime;

public PrintProcessor(){
jodaTime = new JodaTime();
}
...
public String getPrintJobName(Shipper shipper){
String printJobName = null;
//Get current EST time
if(jodaTime.getCurrentDateTimeEST().isBefore(jodaTime.getFourPM_EST()) ||
jodaTime.getCurrentDateTimeEST().isAfter(jodaTime.getSevenPM_EST())){ //Before 4PM EST and after 7PM EST
switch(shipper){
case X:
...
}else if(jodaTime.getCurrentDateTimeEST().isBefore(jodaTime.getSevenPM_EST())){ //Between 4PM-7PM EST
switch(shipper){
case X:
...
}
return printJobName;
}
}

如您所见,printJobName 取决于相对于美国东部标准时间 [4PM-7PM] 时间间隔的当前时间和发件人名称。由于 Shipper 将通过参数传递,我们可以毫无问题地对其进行单元测试。但我需要 mock 时间。所以这就是我的尝试

@Test
public void testGetPrintJobNameBeforeFourPM(){
DateTime current = new DateTime(DateTimeZone.forID("EST"));
Clock clock = mock(Clock.class);
//Always return 6pm when I try to ask for the current time
when(clock.getCurrentDateTimeEST()).thenReturn(new DateTime(current.getYear(), current.getMonthOfYear(),
current.getDayOfMonth(), 18, 0, 0, 0, DateTimeZone.forID("EST")));
//Test for Fedex
String printJobName = printProcessor.getPrintJobName(Shipper.X);
assertEquals("XNCRMNCF", printJobName);
}

测试应该失败,因为我在下午 6 点通过,但 XNCRMNCF 是下午 4 点之前的名称。我还需要模拟 printProcessor 吗?如果我的东西是错的。我该如何解决? 我正在努力学习编写高级java代码,请批评我的代码。好想学

最佳答案

这是一个典型的测试案例,显示了设计中的潜在缺陷。您不能模拟 JodaTime,因为您对被测类中的这些类具有硬连线依赖性。

看看 SOLID principles理解为什么这可能是一个问题(特别是在这种情况下 Dependency Inversion Principle )。如果您将 JodaTime 作为依赖项注入(inject)某处,那么在您的单元测试中,您将能够用 mock, stub or spy 替换它的真实实例。视情况而定。

但是: JodaTime 是极不可能在生产环境中注入(inject)任何其他东西的东西,无论它存在多久。相反,在这种情况下,使用 Composed Method Design Pattern 可能会更好。 .在这里,您可以将用于生成 printjobName 的任何计算/算法提取到另一个方法(我在这里看不到您是如何执行的,因为您的代码片段从未为该变量赋值)。然后你可以监视(部分模拟)你的被测类只模拟该方法并返回一个固定值,而不考虑 JodaTime 提供的实际日期时间,例如:

public class PrintProcessor {
...
public String getPrintJobName(Shipper shipper) {
String printJobName = null;
String timeHash = this.getTimeHash();
if (this.isBeforeFourPM()) {
switch(shipper) {
printJobName = // Do something with timeHash to generate name
}
} else {
...
}
return printJobName;
}

public boolean isBeforeFourPM() {
return (jodaTime.getCurrentDateTimeEST().isBefore(jodaTime.getFourPM_EST()) ||
jodaTime.getCurrentDateTimeEST().isAfter(jodaTime.getSevenPM_EST()));
}

public String getTimeHash() {
... // Do something to hash the time value in to a String
}
}

现在你可以在你的测试中写:

@Test
public void testGetPrintJobNameBeforeFourPM() {
PrintProcessor concretePrintProcessor = new PrintProcessor();
PrintProcessor printProcessor = spy(concretePrintProcessor);
doReturn(true).when(printProcessor).isBeforeFourPM();

String printJobName = printProcessor.getPrintJobName(Shipper.X);

assertEquals("XNCRMNCF", printJobName);
}

关于java - Mockito:如何模拟 JodaTime 的界面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6049777/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com