静态实用程序 Class、单元测试和 Java.Time

Static Utility Class, Unit Testing and Java.Time

由于我们的客户仍在使用 Java.Date.Util,我们不得不处理各种转换方法和庞大臃肿的日期实用程序 class。我的目标是简化实用程序 class 并为其编写单元测试。

我已经设法简化了它,但是我 运行 遇到了测试用例的问题,因为:

  1. 作为实用程序 class,方法是静态的,因此没有依赖性 使用 Java.Time.Clock.
  2. 注入
  3. 我们的一些辅助方法在将其转换为请求的格式之前使用 instant.now()。显然,这使得编写单元测试...有问题。

以下是我需要编写测试用例的一些方法示例:

     /**
     * Get the current time in any format.
     * @param outFormat
     * @return
     */
    public static Object getNow(TimeFormat outFormat){
        Instant dateObject = Instant.now();
        
        return new InstantConverter().convertTo(dateObject, outFormat);

    }
    
    /**
     * @param value - unit of time 
     * @param unit  - hours, days, etc. Anything higher than days is not supported. 
     * @param format - format returned. 
     */
    public static Object calculateFutureDate(int value, ChronoUnit unit, TimeFormat outFormat) {
        Instant time = Instant.now().plus(value, unit);
        
        return new InstantConverter().convertTo(time, outFormat);
    }

InstantConverter 是一个受保护的 class,可将 Instant 转换为各种时间输出(本地日期、字符串、纪元、java.util.date 等),而 TimeFormat 是一个枚举,包含我们可以转换成的所有格式。

我知道在单元测试方面最好不要使用静态方法...但恐怕这不是一个选择。

在我的研究中,似乎我唯一的选择是使用 powermock 或 mockito 的较新版本之一来模拟我的静态 instant.now() 方法(类似于:https://rieckpil.de/mocking-static-methods-with-mockito-java-kotlin/)。

我只是想确保我没有遗漏任何明显的东西,因为我不想再次重构,因为我犯了一个错误。

感谢所有花时间阅读本文的人!如果您有任何问题,请告诉我。

没有什么可以阻止您将 Clock 注入包含静态实用程序方法的 class。

  1. 声明一个 private static Clock 字段(一个 class 变量)。在声明中将其初始化为 Clock.systemUTC()Clock.systemDefaultZone()
  2. 让您的静态时间敏感方法使用刚刚介绍的Clock
  3. 有一个包私有(默认可访问)静态 injectsetClock 方法将 Clock 注入静态变量。
  4. 如果需要,可以使用 uninject 方法将 Clock 设置回其初始值。

将单元测试放在同一个包中,以便它们可以使用包私有注入方法。您可能已经发现,测试静态实用程序方法的测试方法首先注入其所需的 Clock,然后调用该方法来测试并验证该方法的 return 值。由于 Clock 是静态的,测试不能 运行 并行。