【问题标题】:How to mock LocalDatTime.now() using mockito?如何使用 mockito 模拟 LocalDatTime.now()?
【发布时间】:2020-06-24 00:28:58
【问题描述】:

我正在为我的商务课程编写单元测试,我想根据我的测试将 LocalDateTime 模拟到特定时间。这是我的功能:

    private fun isExpired(access: Access): Boolean {
        return access.validUntil.isAfter(LocalDateTime.now())
    }

如何模拟LocalDateTime.now()

【问题讨论】:

  • 为什么不能使用“of”方法docs.oracle.com/javase/8/docs/api/java/time/…
  • 为什么要传递 localdatetime 作为函数参数?是不是可以mock一下?
  • 现在是最终类的静态方法,Mockito 无法模拟:github.com/mockito/mockito/wiki/…
  • 顺便说一句,我无法想象调用LocalDateTime.now 是正确的做法。该类型不能代表一个时刻,也不是时间线上的一个点,因为它故意缺少时区的上下文或与 UTC 的偏移量。因此,使用该类来捕捉当前时刻是没有意义的。我敢打赌你真的需要Instant.nowZonedDateTime.now

标签: java unit-testing kotlin mocking mockito


【解决方案1】:

我的建议是你注入一个对 Clock 的依赖并在你的方法中使用它。抱歉,由于我对 kotlin 不太熟悉,所以我已转换为 Java。

class ClassToTest {
    private final Clock;

    public ClassToTest(Clock clock) {
        this.clock = clock;
    }

    private boolean isExpired(Access access) {
        return access.validUntil.isAfter(LocalDateTime.now(clock));
    }
}

使用固定“现在”的测试看起来像:

@Test
void testIsExpired() {
    Clock clock = mock(Clock.class);
    when(clock.instant()).thenReturn(Instant.ofEpochSecond(1000L));
    when(clock.getZone()).thenReturn(ZoneOffset.UTC);
    ClassToTest test = new ClassToTest(clock);
    assertThat(test.isExpired(access))...
}

您专门询问了关于模拟的问题,但您可以通过恒定时钟实现同样的目的:

@Test
void testIsExpired() {
    Clock clock = Clock.fixed(Instant.ofEpochSecond(1000L), ZoneOffset.UTC);
    ClassToTest test = new ClassToTest(clock);
    assertThat(test.isExpired(access))...
}

您的生产代码将注入您想要的任何时钟(例如特定的 TZ、本地 TZ、每秒滴答的时钟等),这些都是使用静态 Clock 方法创建的。除了测试价值之外,更改时钟的功能通常是一项有用的功能。

【讨论】:

  • 我应该对HttpClientHttpRequest 遵循相同的想法吗?
  • 这个场景正是为什么Clock是API的一部分。我会注意到,拥有 private Clock clock = systemUTC() 和通常不使用的 setter 并非完全不合理。
猜你喜欢
  • 2016-05-08
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多