Mockito 验证 'arguments are different',而它们是相同的

Mockito verify 'arguments are different', while they are identical

我正在测试 spring RestController。我用几辆婴儿车来呼叫控制器。通话成功,我得到了预期的回应。但是 Mockito 无法验证服务的模拟调用。为什么?:

...
    private static final String TRACE_ID = "1";
    private static final String MAPPED_ID = "2";
...


    @Test
    void getLogMessages() throws Exception {
        LogMessageDto dto = easyRandom.nextObject(LogMessageDto.class);
        Integer slice = 0;
        Integer limit = 60;
        Integer serviceLimit = 50;
        Date startFrom = new Date();
        Date startTo = new Date();
        MultiValueMap<String, String > params = new LinkedMultiValueMap<>();
        params.put("traceId", Collections.singletonList(TRACE_ID));
        params.put("mappedId", Collections.singletonList(MAPPED_ID));
        params.put("slice", Collections.singletonList(slice.toString()));
        params.put("limit", Collections.singletonList(limit.toString()));
        params.put("startFrom", Collections.singletonList(startFrom.toString()));
        params.put("startTo", Collections.singletonList(startTo.toString()));
        Mockito.when(logMessageService.getLogMessages(anyString(), anyString(), anyInt(), anyInt(), any(Date.class),
                        any(Date.class)))
                .thenReturn(new PageImpl<>(Collections.singletonList(dto)));
        mockMvc.perform(get("/feed-logs-service/messages")
                        .queryParams(params))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.content[0].content", equalTo(asParsedJson(dto.getContent()))))
                .andExpect(jsonPath("$.content[0].fields", equalTo(asParsedJson(dto.getFields()))));
        verify(logMessageService).getLogMessages(eq(TRACE_ID), eq(MAPPED_ID), eq(slice), eq(serviceLimit), eq(startFrom),
                eq(startTo));
        verifyNoMoreInteractions(logMessageService);
    }

测试执行结果:

Argument(s) are different! Wanted:
service.LogMessageService#0 bean.getLogMessages(
    "1",
    "2",
    0,
    50,
    Sun Feb 06 14:52:13 MSK 2022,
    Sun Feb 06 14:52:13 MSK 2022
);
-> at controller.LogMessageControllerTest.getLogMessages(LogMessageControllerTest.java:97)
Actual invocations have different arguments:
service.LogMessageService#0 bean.getLogMessages(
    "1",
    "2",
    0,
    50,
    Sun Feb 06 14:52:13 MSK 2022,
    Sun Feb 06 14:52:13 MSK 2022
);

intellij idea点击'Click to see difference'link时多了一个空行,请问是什么原因,请问如何过槽?感谢您的任何建议。

编辑: 控制器方法:

    @GetMapping("/messages")
    public Page<LogMessageDto> getLogMessages(@RequestParam String traceId, @RequestParam String mappedId,
            @RequestParam(required = false) Integer slice,
            @RequestParam(required = false, defaultValue = SIZE_LIMIT) Integer limit,
            @RequestParam(required = false) @DateTimeFormat(pattern = "EEE MMM dd HH:mm:ss ZZZ yyyy") Date startFrom,
            @RequestParam(required = false) @DateTimeFormat(pattern = "EEE MMM dd HH:mm:ss ZZZ yyyy") Date startTo) {
        limit = checkLimit(limit);
        return logMessageService.getLogMessages(traceId, mappedId, slice, limit, startFrom, startTo);
    }

来自测试:

Date startFrom = new Date();

这些值被解析为字符串:

params.put("startFrom", Collections.singletonList(startFrom.toString()));

但是在验证它不是验证的字符串表示时:

verify(logMessageService).getLogMessages(..., eq(startFrom), ...);

我可以告诉你这个问题。但作为学习 Date 工作原理的练习,我建议您比较测试中创建的变量中的 startFrom.getTime() 和对 logMessageService.getLogMessages(...)

的调用

编辑以添加对问题的解释

日期在内部表示为 64 位整数,精确到毫秒。这就是调用 equals-method 时使用的内容。当调用 toString 方法时,它会转换为人类可读的格式,并且默认情况下会丢失毫秒位。当它在控制器中转换回日期时,它的毫秒数为零。以毫秒为单位根据日期进行验证。