我正在为REST控制器编写测试用例。代码如下:
private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yy");
@Test
public void getByExternalTransactionId() throws Exception {
EquityFeeds equityFeeds = new EquityFeeds(423,"SAPEXTXN1", "GS", "ICICI", "BUY", dateFormat.parse("22/11/13"), 101.9f, "BLO", "Y",0);
when(equityFeedsService.findByExternalTransactionId("SAPEXTXN1")).thenReturn(equityFeeds);
mockMvc.perform(MockMvcRequestBuilders.get("/equityFeeds/getByExternalTransactionId/{externalTransactionId}", "SAPEXTXN1"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.*", Matchers.hasSize(10)))
.andExpect(jsonPath("$.id", Matchers.is(423)))
.andExpect(jsonPath("$.externalTransactionId", Matchers.is("SAPEXTXN1")))
.andExpect(jsonPath("$.clientId", Matchers.is("GS")))
.andExpect(jsonPath("$.securityId", Matchers.is("ICICI")))
.andExpect(jsonPath("$.transactionType", Matchers.is("BUY")))
// .andExpect(jsonPath("$.transactionDate", Matchers.is(dateFormat.parse("22/11/13"))))
.andExpect(jsonPath("$.transactionDate", Matchers.is(Date.parse("22/11/13"))))
.andExpect(jsonPath("$.marketValue", Matchers.is(101.9f)))
.andExpect(jsonPath("$.sourceSystem", Matchers.is("BLO")))
.andExpect(jsonPath("$.priorityFlag", Matchers.is("Y")))
.andExpect(jsonPath("$.processingFee", Matchers.is(0)));
verify(equityFeedsService, times(1)).findByExternalTransactionId("1");
verifyNoInteractions(equityFeedsService);
}
问题:不幸的是:-(我的一个字段是POJO类中的java.util.Date。它在transactionDate中被破坏了,而后者在POJO中是java.util.Date。我在下面的测试用例中尝试过:
.andExpect(jsonPath("$.transactionDate", Matchers.is(dateFormat.parse("22/11/13"))))
这给我输出
java.lang.AssertionError: JSON path "$.transactionDate"
Expected: is <Fri Nov 22 00:00:00 IST 2013>
but: was <1385058600000L>
Expected :is <Fri Nov 22 00:00:00 IST 2013>
Actual :<1385058600000L>
然后我尝试:
.andExpect(jsonPath("$.transactionDate", Matchers.is(Date.parse("22/11/13"))))
这给了我输出:
java.lang.AssertionError: JSON path "$.transactionDate"
Expected: is <1412965800000L>
but: was <1385058600000L>
Expected :is <1412965800000L>
Actual :<1385058600000L>
这看起来非常接近。我知道值的差异是因为在POJO中创建日期的时间是毫秒,与.andExpect(jsonPath("$.transactionDate", Matchers.is(Date.parse("22/11/13"))))
行中创建日期的时间是不同的,因此值是不同的,因为值也很长,因为值以毫秒为单位。
我的TestCase仅由于此字段而失败。我真的不知道该如何解决这个问题。我只需要使用java.util.Date。还有其他解决方案吗?请帮助我解决这个问题。我被困住了。
如果我理解正确(不熟悉Hamcrest,您的程序给出的是long
值1385058600000L
或1 385 058 600 000,并且您希望您的测试检查是否是这种情况。
在给定日期字符串22/11/13
的情况下,这是产生期望值的方法。
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("d/M/yy");
ZoneId zone = ZoneId.of("Asia/Kolkata");
String expectedDate = "22/11/13";
long expectedTransactionDateMillis = LocalDate
.parse(expectedDate, dateFormatter)
.atStartOfDay(zone)
.toInstant()
.toEpochMilli();
System.out.println(expectedTransactionDateMillis);
输出为:
1385058600000
[不熟悉Hamcrest,也没有尝试过,我希望您只需要在断言中填充此值:
.andExpect(jsonPath("$.transactionDate", Matchers.is(expectedTransactionDateMillis)))
java.util.Date
类的设计很差,而且已经过时了。我建议您不要使用它,甚至更强烈建议您不要使用臭名昭著的SimpleDateFormat
类。尽管出于历史原因在生产代码中使用了Date
,但我认为没有理由在测试中重复该错误。使用java.time,可以更好地使用它。
您的首次尝试:
.andExpect(jsonPath("$.transactionDate", Matchers.is(dateFormat.parse("22/11/13"))))
dateFormat.parse("22/11/13")
的结果是java.util.Date
。即使它等于POJO中的Date
,但JSON中的值仍是long
,表示自纪元以来的毫秒数(如果可能的话,可能需要更改此做法)。由于Date
和long
不能相等,因此测试失败。
您然后尝试了:
.andExpect(jsonPath("$.transactionDate", Matchers.is(Date.parse("22/11/13"))))
现在您将获得long
值。我们可以看到期望值和实际值在打印输出中具有相同的格式。有两件事是错误的:
Date.parse
方法。之所以如此,是因为该方法在各个时区中的工作方式都不可靠。即使您坚持使用Date
,仍应远离那些不赞成使用的方法和构造函数。parse
方法只是推论而来,一直计数到2014年并于当年10月结束。不使用该方法的另一个原因。Oracle tutorial: Date Time解释如何使用java.time。