我有一个班级,我计算当前日期(now
)和其他日期(birthday
)之间的年份差异:
import java.util.Date;
import org.joda.time.LocalDate;
import org.joda.time.Years;
public class Logic {
private final Date now;
public Logic(final Date curDate) {
now = curDate;
}
[...]
protected int getAgeInYears(final Date now, final Date birthday) {
final LocalDate nowDate = new LocalDate(now.getTime());
final LocalDate birthdayDate = new LocalDate(birthday.getTime());
return Years.yearsBetween(birthdayDate, nowDate).getYears();
}
}
然后我有一个单元测试,它验证getAgeInYears
:
public class SomeTest {
@Test
public void test() {
final LocalDate now = new LocalDate(2015, 8, 28);
final Logic objectUnderTest =
new Logic(now.toDate());
final LocalDate birthDay1 = new LocalDate(2015 - 7, 8, 28);
Assert.assertEquals(6,
objectUnderTest.getAgeInYears(now.toDate(), birthDay1.toDate())); // This assertion fails sometimes, but not always
final LocalDate birthDay2 = new LocalDate(2015 - 7, 8, 27);
Assert.assertEquals(7,
objectUnderTest.getAgeInYears(now.toDate(), birthDay2.toDate()));
final LocalDate birthDay3 = new LocalDate(1981, 4, 24);
Assert.assertEquals(34,
objectUnderTest.getAgeInYears(now.toDate(), birthDay3.toDate()));
}
}
断言
Assert.assertEquals(6,
objectUnderTest.getAgeInYears(now.toDate(), birthDay1.toDate()));
有时会失败。
在我的机器上,测试运行没有错误。在其中一个测试失败的构建服务器(Java 6)上。当我使用Java 6在本地重建代码时,测试没有失败。
什么可能导致这种奇怪的行为?
更新1:错误消息为expected:<6> but was:<7>
。
更新2:我重写了代码以摆脱toDate
来电并得到了这个:
public class Logic {
private final LocalDate now;
public Logic(final LocalDate curDate) {
now = curDate;
}
[...]
protected int getAgeInYears(final LocalDate now, final LocalDate birthday) {
final LocalDate nowDate = new LocalDate(now);
final LocalDate birthdayDate = new LocalDate(birthday);
return Years.yearsBetween(birthdayDate, nowDate).getYears();
}
}
public class LogicTest {
@Test
public void getAgeInYearsSunnyDay() {
final LocalDate now = new LocalDate(2015, 8, 28);
final AdditionalServicesLogic objectUnderTest =
new AdditionalServicesLogic(now);
final LocalDate birthDay1 = new LocalDate(2015 - 7, 8, 28);
Assert.assertEquals(7,
objectUnderTest.getAgeInYears(now, birthDay1));
final LocalDate birthDay2 = new LocalDate(2015 - 7, 8, 27);
Assert.assertEquals(6,
objectUnderTest.getAgeInYears(now, birthDay2));
final LocalDate birthDay3 = new LocalDate(1981, 4, 24);
Assert.assertEquals(34,
objectUnderTest.getAgeInYears(now, birthDay3));
}
}
现在我经常在线上获得断言错误
Assert.assertEquals(6,
objectUnderTest.getAgeInYears(now, birthDay2));
我希望得到6,但得到7。
答案 0 :(得分:1)
您应该从java.util.Date
课程中删除Logic
,并在此处仅使用joda课程。这将使您的代码更加清晰,因为无需在LocalDate
和Date
之间进行转换。实际上这样做会让你的测试变得毫无意义,因为你只会测试joda时间的Years.yearsBetween
,我希望它已经被测试了。
我怀疑该错误可能在您的LocalDate
/ Date
转换时出现,您应该通过将now.toDate()
和birthDay1.toDate()
的实际值打印到测试日志来检查。并查看LocalDate.toDate的javadoc:
转换为JDK日期与JDK日期一样充满复杂性 构造函数不像DST转换那样表现。 此方法通过先猜测然后调整JDK来工作 日期,直到它有最早的有效时刻。这也处理了 JDK时区数据与Joda-Time时间不同的情况 区域数据。
答案 1 :(得分:1)
Joda-Time是正确的记住您的代码:
您已明确将birthDay2
设置为2008-08-27。你现在变量是2015-08-28的日期。因此,如果您在birthDay2
添加7年后,您将获得2015-08-27的日期,该日期仍比2015-08-28早一天。
如果您现在= 2015-08-27(那么差异恰好是7年),7年的结果将不会改变。
如果您将birthDay2
设置为2008-08-28而现在= 2015-08-27(因为这里的日期比较可以防止完整的7年),那么期望6年是正确的-delta)。
小旁注:
闰日有一个特殊情况,需要一些关注(这里我认为Joda-Time是错误的) - 请参阅此关闭的issue。