的Mockito.捕获对LocalDateTime.now()的调用;

Pat*_*ick 1 time junit unit-testing mockito

我正在进行一个单元测试,它调用一个类并检查该类中的方法是否已使用某些参数调用.其中一个参数是LocalDateTime.now().

我的问题是,当控制回到我的JUnit测试时,时间已经开始,所以如果我尝试比较我用当前时间调用的类中使用的时间,它们就不会匹配.

这是我正在研究的方法:

ServiceStatus serviceStatus = ServiceStatus.createNew(LocalDateTime.now());
Run Code Online (Sandbox Code Playgroud)

Junit测试是:

verify(service).saveNotice(LocalDateTime.now));
Run Code Online (Sandbox Code Playgroud)

我试过TimeFactory用来修复日期:

given(timeFactory.currentDateTime()).willReturn(NOW);
Run Code Online (Sandbox Code Playgroud)

其次是:

given(message.getHeader("MESSAGE_CREATED_TIME")).willReturn(NOW.toString());
Run Code Online (Sandbox Code Playgroud)

&

verify(service).saveNotice(NOW));
Run Code Online (Sandbox Code Playgroud)

但没有快乐.

有什么建议?

(PS.在实际代码中还有其他参数,但为了简单起见和出于商业机密的原因,我将它们删除了.)

Jef*_*ica 7

不要使用PowerMock.使用/模拟时钟代替.切换您的来电LocalDateTime.now()LocalDateTime.now(clock).来自时钟文档:

应用程序的最佳实践是将Clock传递给任何需要当前瞬间的方法.依赖注入框架是实现此目的的一种方法:

public class MyBean {
  private Clock clock;  // dependency inject
  ...
  public void process(LocalDate eventDate) {
    if (eventDate.isBefore(LocalDate.now(clock)) {
      ...
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这种方法允许在测试期间使用备用时钟,例如固定或偏移.

一种策略是制作clock最终版本,并提供两个构造函数 - 一个使用提供的时钟,另一个使系统时钟超出Clock.systemDefaultZone()Clock.systemUTC().另一种方法是将Clock字段设置为可测试,可能将其保留为package-private.在任何一种情况下,您都可以通过提供创建的Clock轻松覆盖该值Clock.fixed(...),或者如果您需要在整个测试期间进行更改,则可以编写自己的实现.


Gho*_*ica 5

我建议不要使用PowerMock。

你的问题是静态调用now(). 它可能看起来有点过度设计,但认真考虑简单地在静态调用周围放置一些小接口/类,例如:

interface TimeStampProvider {
  LocalDateTime getNow();
}
Run Code Online (Sandbox Code Playgroud)

其“impl”可以简单地调用 LocalDateTime.now() 。

但问题是:现在您只需将 TimeStampProvider 对象传递给您的类(您可以完美地模拟它,而不需要 PowerMock)。

你看:从长远来看,Powermock可能会导致各种有趣的奇怪问题;尤其是在编写自己代码时:只需提出更好的设计即可;而不是尝试使用 PowerMock“修复”(部分)损坏的设计。