我有一个方法toUTC()
public ZonedDateTime toUTC(LocalDateTime ldt) {
return ldt.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneOffset.UTC);
}
我想为这种方法编写一个测试,但我不确定最好的方法吗?有人能指出我正确的方向吗?我不是一个约会时间和时区专家
答案 0 :(得分:1)
首先,您的方法无法编译。我得到了
类型不匹配:无法从ZonedDateTime转换为LocalDateTime
原则上,这很好,因为它允许我们至少一定程度的TDD:在方法之前(完成)编写测试。另一方面,当我们不确定该方法的要求时,编写测试是一项挑战。它应该返回当前签名所暗示的LocalDateTime
,或者更确切地说是返回语句尝试的ZonedDateTime
,或者可能是OffsetDateTime
,因为我们知道目标偏移,甚至是Instant
1}},因为这些始终是UTC?
OffsetDateTime
,方法如下:
public static OffsetDateTime toUTC(LocalDateTime ldt) {
return ldt.atZone(ZoneId.systemDefault())
.toOffsetDateTime()
.withOffsetSameInstant(ZoneOffset.UTC);
}
下一个挑战是我们的方法取决于ZoneId.systemDefault()
。这种依赖性降低了可测试性,因为我们希望测试在所有时区中运行,但该方法不应在所有时区中产生相同的结果。我没有搜索过操纵系统默认时区的方法,它们可能存在,并且有一些模拟框架可以让我们存根ZoneId.systemDefault()
并控制它返回给我们方法的结果。我将在这里使用的简单方法是重构,解决了麻烦的依赖:
public static OffsetDateTime toUTC(LocalDateTime ldt) {
return fromZoneToUtc(ldt, ZoneId.systemDefault());
}
static OffsetDateTime fromZoneToUtc(LocalDateTime ldt, ZoneId timeZone) {
return ldt.atZone(timeZone).toOffsetDateTime().withOffsetSameInstant(ZoneOffset.UTC);
}
我放弃测试上面第一个非常简单的方法,但测试第二个,所有逻辑发生的地方,现在可以使用常量数据完成,例如
assertEquals(OffsetDateTime.of(2017, 4, 12, 14, 0, 0, 0, ZoneOffset.UTC),
fromZoneToUtc(LocalDateTime.of(2017, 4, 12, 16, 0), ZoneId.of("Europe/Berlin")));
我会留给你找一些好的测试用例。我相信你可以想到一些不同的时区,一些区域有DST,有些区域没有。 UTC东部和西部的区域以及与UTC重合的区域(在测试年份时)。有些时候是在夏季,有些是在冬季,最好是一些接近DST交叉(春季和秋季)。