在单元测试中使用Hamcrest匹配java.util.Date的问题

问题描述 投票:0回答:1

我正在为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"))))行中创建日期的时间是不同的,因此值是不同的,因为值也很长,因为值以毫秒为单位。

我的T​​estCase仅由于此字段而失败。我真的不知道该如何解决这个问题。我只需要使用java.util.Date。还有其他解决方案吗?请帮助我解决这个问题。我被困住了。

unit-testing spring-restcontroller hamcrest java.util.date
1个回答
0
投票

如果我理解正确(不熟悉Hamcrest,您的程序给出的是long1385058600000L或1 385 058 600 000,并且您希望您的测试检查是否是这种情况。

java.time

在给定日期字符串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,表示自纪元以来的毫秒数(如果可能的话,可能需要更改此做法)。由于Datelong不能相等,因此测试失败。

您然后尝试了:

            .andExpect(jsonPath("$.transactionDate", Matchers.is(Date.parse("22/11/13"))))

现在您将获得long值。我们可以看到期望值和实际值在打印输出中具有相同的格式。有两件事是错误的:

  1. 您使用的是自1997年以来不推荐使用的Date.parse方法。之所以如此,是因为该方法在各个时区中的工作方式都不可靠。即使您坚持使用Date,仍应远离那些不赞成使用的方法和构造函数。
  2. 您的日期字符串被解析为1 412 965 800 000,等于2014-10-11T00:00 + 05:30,所以已经快一年了。该方法不仅被弃用,而且令人困惑,并将您的日期字符串解析为2013年第22个月的第11天。没有一年中的第22个月,但parse方法只是推论而来,一直计数到2014年并于当年10月结束。不使用该方法的另一个原因。

链接

Oracle tutorial: Date Time解释如何使用java.time。

© www.soinside.com 2019 - 2024. All rights reserved.