由于时区不同导致时间戳时间不匹配
Timestamp time mismatch because of the different time zone
我的团队收到了一个新项目。该项目有一堆未通过的测试。用他们的话说,所有的测试都应该通过。调查问题后,我发现存在一个常见问题。大多数失败的测试都会创建 Timestamp
并使用它,但预期日期和实际日期不同。时差恰好是一小时。旧开发团队一直在 GMT + 1 的区域工作,而我们在 GMT + 2 工作。
为什么会发生这种情况?
编辑:
我有一个创建实体 Rating
并设置一堆属性的测试。例如:
rating.setValidFromDate(new Timestamp(1459841866798L));
然后测试声明一个预期的字符串常量和 rating.toString()
正如我所说,时差恰好是 1 小时
编辑 2:
@Test
public void testToString() {
Rating rating = new Rating();
rating.setValidFromDate(new Timestamp(1459841866798L));
assertEquals("Rating{validFromDate='2016-04-05 09:37:46'}", rating.toString());
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(Rating.class.getSimpleName());
builder.append("{");
builder.append("validFromDate='" + DateHelper.getStringFromDate(validFromDate) + "'");
builder.append("}");
return builder.toString();
}
public static String getStringFromDate(Date dateValue) {
String strDate = "";
if (dateValue != null) {
DateFormat dateFormat = new SimpleDateFormat(Constants.DATETIME_FORMAT);
strDate = dateFormat.format(dateValue);
}
return strDate;
}
已解决
我决定给你解决这个问题的方法。
读完这篇文章后:java.sql.Timestamp: changing timezone of Timestamp我找到了一种操纵测试时区的方法。所以我决定编写一个 JUnit 规则,它将对我的所有测试执行此操作。
我写了以下声明:
public class GermanTimeZoneStatement extends Statement {
private final Statement base;
public GermanTimeZoneStatement(Statement base) {
super();
this.base = base;
}
@Override
public void evaluate() throws Throwable {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
base.evaluate();
}
}
之后我写了这条规则:
public class GermanTimeZoneRule implements TestRule {
public static GermanTimeZoneRule getInstance() {
return new GermanTimeZoneRule();
}
@Override
public Statement apply(Statement base, Description description) {
return new GermanTimeZoneStatement(base);
}
}
最后,我在我的测试中包含了这样的规则:
@Rule
public GermanTimeZoneRule germanTimeZoneRule = GermanTimeZoneRule.getInstance();
您正在测试的代码取决于时区。它根据用户默认时区中的时间输出特定日期。这就是为什么它给你的输出与它给你的同事的不同。
您需要返回到该代码的规范,并检查这是否是预期的行为。如果是,则需要修改测试以将时区考虑在内。如果这不是预期的行为,那么恭喜,您的测试暴露了一个错误!
我的团队收到了一个新项目。该项目有一堆未通过的测试。用他们的话说,所有的测试都应该通过。调查问题后,我发现存在一个常见问题。大多数失败的测试都会创建 Timestamp
并使用它,但预期日期和实际日期不同。时差恰好是一小时。旧开发团队一直在 GMT + 1 的区域工作,而我们在 GMT + 2 工作。
为什么会发生这种情况?
编辑:
我有一个创建实体 Rating
并设置一堆属性的测试。例如:
rating.setValidFromDate(new Timestamp(1459841866798L));
然后测试声明一个预期的字符串常量和 rating.toString()
正如我所说,时差恰好是 1 小时
编辑 2:
@Test
public void testToString() {
Rating rating = new Rating();
rating.setValidFromDate(new Timestamp(1459841866798L));
assertEquals("Rating{validFromDate='2016-04-05 09:37:46'}", rating.toString());
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(Rating.class.getSimpleName());
builder.append("{");
builder.append("validFromDate='" + DateHelper.getStringFromDate(validFromDate) + "'");
builder.append("}");
return builder.toString();
}
public static String getStringFromDate(Date dateValue) {
String strDate = "";
if (dateValue != null) {
DateFormat dateFormat = new SimpleDateFormat(Constants.DATETIME_FORMAT);
strDate = dateFormat.format(dateValue);
}
return strDate;
}
已解决
我决定给你解决这个问题的方法。
读完这篇文章后:java.sql.Timestamp: changing timezone of Timestamp我找到了一种操纵测试时区的方法。所以我决定编写一个 JUnit 规则,它将对我的所有测试执行此操作。
我写了以下声明:
public class GermanTimeZoneStatement extends Statement {
private final Statement base;
public GermanTimeZoneStatement(Statement base) {
super();
this.base = base;
}
@Override
public void evaluate() throws Throwable {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
base.evaluate();
}
}
之后我写了这条规则:
public class GermanTimeZoneRule implements TestRule {
public static GermanTimeZoneRule getInstance() {
return new GermanTimeZoneRule();
}
@Override
public Statement apply(Statement base, Description description) {
return new GermanTimeZoneStatement(base);
}
}
最后,我在我的测试中包含了这样的规则:
@Rule
public GermanTimeZoneRule germanTimeZoneRule = GermanTimeZoneRule.getInstance();
您正在测试的代码取决于时区。它根据用户默认时区中的时间输出特定日期。这就是为什么它给你的输出与它给你的同事的不同。
您需要返回到该代码的规范,并检查这是否是预期的行为。如果是,则需要修改测试以将时区考虑在内。如果这不是预期的行为,那么恭喜,您的测试暴露了一个错误!