java - Java,TDD 不等于时为真?
问题描述
出于某种原因,在课堂上测试此方法时,我们发现了一个我们无法理解的问题。System.out.println();
当出于某种原因写作时它通过了?有人可以解释为什么会这样吗?
public class Zones {
public ZoneId getZoneId(String input) {
if (input.equalsIgnoreCase("Stockholm")) {
return ZoneId.of("Europe/Stockholm");
}
else if (input.equalsIgnoreCase("Shanghai")) {
return ZoneId.of("Asia/Shanghai");
} else if (input.equalsIgnoreCase("Toronto")) {
return ZoneId.of("America/Toronto");
}
else if (input.equalsIgnoreCase("Hamburg")) {
return ZoneId.of("Europe/Berlin");
}
else return null;
}
public LocalDateTime getZoneTime(ZoneId zoneId) {
LocalDateTime lt = LocalDateTime.now(zoneId);
return lt;
}
}
private Zones z = new Zones();
@Test
public void getZoneTimeTest () {
System.out.println(z.getZoneTime(zIDToronto).getNano() );
System.out.println(LocalDateTime.now(zIDToronto).getNano() );
assertTrue(z.getZoneTime(zIDToronto).getNano() == LocalDateTime.now(zIDToronto).getNano());
}
解决方案
终于有时间更深入地调查了。
我开始试验,过了一会儿发现,实际上System.out.println
影响结果的不是它的存在,而是你LocalDateTime
在它之前实例化了 2 个实例。
深入挖掘LocalDateTime
和SystemClock
(它所委托的)代码,我发现亚毫微精度是通过调用本机调用实现的jdk.internal.misc.VM#getNanoTimeAdjustment
。
最后一次调用是特定于操作系统的。我对它进行了一些试验,发现它不会线性返回值,因为它在循环中被调用(假设我的循环运行得相当规律)。
所以我决定运行一些代码来映射返回的 nano 值。
我做了这个采样代码:
Clock clock = Clock.systemDefaultZone();
int samples = 1_000;
LocalDateTime[] instants = new LocalDateTime[samples];
int k = 0;
for (int i = 0; i < samples; i++) {
instants[i] = LocalDateTime.now(clock);
for (int j = 0; j < 10000; j++) {
k = j % 2;
}
}
将值写入文件,然后将纳米差异与第一个值映射到图表中:
As you can see this graph (of 1000 values) makes intermittent leaps. This is obviously in part due to precision restriction of the underlying system. But wat struck me is that the first two values consistently were different. It's as if upon regular access the OS system starts caching the value for a while (possibly to avoid strain on the system resources).
But the result it seems is that you set yourself up for getting the same value on the 3rd and 4th call (unless enough time has passed).
That would explain why your test passes with, and fails without those prior instantiations.
顺便说一句,对于单元测试,您不想依赖系统时钟。确保您的业务代码从注入的 Clock 实例中获取时间。然后,您可以为测试注入自定义时钟,并测试您的代码是在 DST 转换日期还是在闰日运行,而无需等待几个月。
推荐阅读
- c++ - 循环遍历枚举的好方法是什么?
- python - Django过滤器记录到松弛通道
- haskell - Pop 无法正常工作,堆栈始终为空
- javascript - 显示感谢信息并重定向到另一个页面
- python - 运行 webscrape 测试时“获取默认适配器失败”
- python - 从 Windows Dock 最小化 PyQt5 应用程序使应用程序处于活动状态
- facebook - 使用 Facebook API 发布到我自己的页面,无需业务验证
- wordpress - 如何通过 woocommerce_subscription_renewal_payment_complete 挂钩更新帖子元?
- python - 为什么 Tesseract 数字识别无法正常工作?
- javascript - 试图从我的 MongoDB (abc.db) 中提取一长串数据