Reputation: 332
I am testing spring RestController. I use several prams to call controller. The call is successful and i got expected response. But Mockito is not able to verify mock call of service. Why?:
...
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);
}
the test execution results in:
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 shows additional empty line when i click 'Click to see difference' link, is it the reason?, and how to pass trough? Thanks for any suggestions.
EDIT: controller method:
@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);
}
Upvotes: 1
Views: 1363
Reputation: 221
From the test:
Date startFrom = new Date();
These values are parsed to a String:
params.put("startFrom", Collections.singletonList(startFrom.toString()));
But when verifying it's not the String representation that's validated:
verify(logMessageService).getLogMessages(..., eq(startFrom), ...);
I could tell you the problem with this. But as an exercise to learn how Date works I suggest you compare the startFrom.getTime() from the variable created in the test, and the call to logMessageService.getLogMessages(...)
Edit to add an explanation of the problem
The Date is represented as a 64 bit integer internally, down to millisecond. That's what's used when the equals-method is called. When the toString method is called it's converted to a human readable format, and by default loses the millisecond bit. When it's converted back to a Date in the controller it's with zeros as the milliseconds. Which is verified against the Date with milliseconds.
Upvotes: 1