我正在做一个单元测试,它调用一个类并检查该类中的方法是否已使用某些参数调用。其中一个参数是 LocalDateTime.now()
.
问题是,当控制回到我的 JUnit 测试时,时间已经前进,所以如果我尝试将我正在调用的类中使用的时间与当前时间进行比较,它们将无法匹配。
这是我正在研究的方法:
ServiceStatus serviceStatus = ServiceStatus.createNew(LocalDateTime.now());
Junit 测试是:
verify(service).saveNotice(LocalDateTime.now));
我尝试使用TimeFactory
来修复日期:
given(timeFactory.currentDateTime()).willReturn(NOW);
其次:
given(message.getHeader("MESSAGE_CREATED_TIME")).willReturn(NOW.toString());
&
verify(service).saveNotice(NOW));
但没有快乐。
有什么建议吗?
(附言。在实际代码中还有其他参数,但为了简单起见和商业机密性,我将它们删除了。
不要使用 PowerMock。改用/模拟时钟。将呼叫切换到LocalDateTime.now()
LocalDateTime.now(clock)
。来自时钟文档:
应用程序的最佳做法是将时钟传递到需要当前时刻的任何方法中。依赖注入框架是实现此目的的一种方法:
public class MyBean { private Clock clock; // dependency inject ... public void process(LocalDate eventDate) { if (eventDate.isBefore(LocalDate.now(clock)) { ... } } }
这种方法允许在测试期间使用备用时钟,例如固定时钟或偏移时钟。
一种策略是使clock
最终,并提供两个构造函数 - 一个使用提供的时钟,另一个使系统时钟脱离Clock.systemDefaultZone()
或Clock.systemUTC()
。另一种方法是使时钟字段可设置为可测试,可能将其保留为包私有。在任何一种情况下,您都可以通过提供由 Clock.fixed(...)
创建的时钟来轻松覆盖该值,或者如果需要它在测试期间进行更改,则可以编写自己的实现。
我建议不要使用PowerMock。
您的问题是对now()
的静态调用。它可能看起来有点过度设计,但认真考虑简单地在静态调用周围放置一些小接口/类,例如:
interface TimeStampProvider {
LocalDateTime getNow();
}
"impl"可以简单地调用LocalDateTime.now()。
但问题是:现在您只需将 TimeStampProvider 对象传递给您的类(您可以完美地模拟它而无需 PowerMock)。
你看:从长远来看,Powermock会导致各种有趣的奇怪问题;特别是在编写自己的代码时:只需提出更好的设计;而不是试图使用PowerMock"修复"(部分)损坏的设计。
我的建议是让你使用PowerMockito。这样,您可以从调用中返回所需的内容 LocalDateTime.now()
.
为此,您或多或少需要以下内容(日历类的示例):
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
// ...
@RunWith(PowerMockRunner.class)
@PrepareForTest({Calendar.class})
public class DateUtilsTest {
public void testWithKnownCalendar(){
PowerMockito.mockStatic(Calendar.class);
PowerMockito.when(Calendar.getInstance(TimeZone.getTimeZone("UTC"))).thenReturn(CalendarObjectFactory.getInstance().buildKnownCalendar(45));
// your normal code here
}
}
通过使用本地日期时间而不是日历来调整它。