【问题标题】:Mockito. Capturing a call to LocalDateTime.now();莫基托。捕获对 LocalDateTime.now() 的调用;
【发布时间】:2017-01-10 17:16:47
【问题描述】:

我正在做一个单元测试,它调用一个类并检查该类中的方法是否已使用某些参数调用。其中一个参数是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));

但没有快乐。

有什么建议吗?

(PS。在实际代码中还有其他参数,但为了简单起见和商业机密,我把它们去掉了。)

【问题讨论】:

  • 我注意到您没有接受答案。请考虑这样做 - 如果您需要更多信息,请随时给我留言。
  • 在类似问题上查看detailed answer,这可能会有所帮助

标签: unit-testing time junit mockito


【解决方案1】:

不要使用 PowerMock。改用/模拟Clock。将您的呼叫切换到 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(...) 创建的时钟来轻松覆盖该值,或者如果您需要在测试期间对其进行更改,则可以编写自己的实现。

【讨论】:

    【解决方案2】:

    我建议不要使用 PowerMock。

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

    interface TimeStampProvider {
      LocalDateTime getNow();
    }
    

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

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

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

    【讨论】:

    • +1 表示不使用 PowerMock 而是使用小界面。这是一个标准的解决方案,甚至是内置的:见Clock。
    【解决方案3】:

    我的建议是您使用 PowerMockito。这样您就可以从调用中返回您想要的内容到LocalDateTime.now()。

    为此,您或多或少需要以下内容(以 Calendar 类为例):

            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
        }
            }
    

    使用 LocalDateTime 而不是 Calendar 来调整它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      相关资源
      最近更新 更多