静态实用程序 Class、单元测试和 Java.Time
Static Utility Class, Unit Testing and Java.Time
由于我们的客户仍在使用 Java.Date.Util,我们不得不处理各种转换方法和庞大臃肿的日期实用程序 class。我的目标是简化实用程序 class 并为其编写单元测试。
我已经设法简化了它,但是我 运行 遇到了测试用例的问题,因为:
- 作为实用程序 class,方法是静态的,因此没有依赖性
使用 Java.Time.Clock.
注入
- 我们的一些辅助方法在将其转换为请求的格式之前使用 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。
- 声明一个
private static Clock
字段(一个 class 变量)。在声明中将其初始化为 Clock.systemUTC()
或 Clock.systemDefaultZone()
。
- 让您的静态时间敏感方法使用刚刚介绍的
Clock
。
- 有一个包私有(默认可访问)静态
inject
或 setClock
方法将 Clock
注入静态变量。
- 如果需要,可以使用
uninject
方法将 Clock
设置回其初始值。
将单元测试放在同一个包中,以便它们可以使用包私有注入方法。您可能已经发现,测试静态实用程序方法的测试方法首先注入其所需的 Clock
,然后调用该方法来测试并验证该方法的 return 值。由于 Clock
是静态的,测试不能 运行 并行。
由于我们的客户仍在使用 Java.Date.Util,我们不得不处理各种转换方法和庞大臃肿的日期实用程序 class。我的目标是简化实用程序 class 并为其编写单元测试。
我已经设法简化了它,但是我 运行 遇到了测试用例的问题,因为:
- 作为实用程序 class,方法是静态的,因此没有依赖性 使用 Java.Time.Clock. 注入
- 我们的一些辅助方法在将其转换为请求的格式之前使用 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。
- 声明一个
private static Clock
字段(一个 class 变量)。在声明中将其初始化为Clock.systemUTC()
或Clock.systemDefaultZone()
。 - 让您的静态时间敏感方法使用刚刚介绍的
Clock
。 - 有一个包私有(默认可访问)静态
inject
或setClock
方法将Clock
注入静态变量。 - 如果需要,可以使用
uninject
方法将Clock
设置回其初始值。
将单元测试放在同一个包中,以便它们可以使用包私有注入方法。您可能已经发现,测试静态实用程序方法的测试方法首先注入其所需的 Clock
,然后调用该方法来测试并验证该方法的 return 值。由于 Clock
是静态的,测试不能 运行 并行。