我正在测试我的 depositUserBalance 端点控制器,这只是一个简单的测试,但我不确定为什么与我的 REST API 中返回的相比,它没有得到正确的响应 JSON。
// My Controller
@PutMapping("/api/deposit")
public ResponseEntity<UserAmountDTO> depositUserBalance(HttpServletRequest request,
@RequestBody UserAmountDTO userAmountDTO) {
Integer userId = (Integer) request.getAttribute("userId");
userAmountDTO = userService.updateUserBalance(userId, userAmountDTO);
return new ResponseEntity<>(userAmountDTO, HttpStatus.OK);
}
// My UserAmountDTO Data Transfer Object
@Getter
@Setter
@AllArgsConstructor
public class UserAmountDTO {
@JsonProperty(access = Access.WRITE_ONLY)
public double amount;
@JsonProperty(access = Access.READ_ONLY)
public double balance;
}
@Test
public void Test_DepositUserBalance() throws Exception {
// Arrange
UserAmountDTO userAmountDTO = new UserAmountDTO(2000.0, 3000.0);
HttpServletRequest request = mock(HttpServletRequest.class);
when(request.getAttribute("userId")).thenReturn(1);
when(userService.updateUserBalance(1, userAmountDTO)).thenReturn(userAmountDTO);
String requestBody = objectMapper.writeValueAsString(userAmountDTO);
System.out.println("requestBody: " + requestBody);
// Act
MvcResult mvcResult = mockMvc.perform(put(DEPOSIT_PATH)
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody).with(requestBuilder -> {
requestBuilder.setAttribute("userId", 1);
return requestBuilder;
}))
.andExpect(status().isOk())
.andReturn();
// Assert
int status = mvcResult.getResponse().getStatus();
String content = mvcResult.getResponse().getContentAsString();
String expectedJson = String.format("{\"balance\":%.1f}", 3000.0);
assertEquals(HttpStatus.OK.value(), status);
assertEquals(expectedJson, content);
}
在我的单元测试中,requestBody 在此处作为余额返回
requestBody: {"balance":3000.0}
而它应该是金额,因为我将 @JsonProperty(acccess = Access.WRITE_ONLY)
设置为金额。
测试的错误是
org.opentest4j.AssertionFailedError: expected: [{"balance":3000.0}] but was: []
。为什么它是一个空字符串?当我在 POSTMAN 的 REST API 中尝试它时,它实际上向我返回了这个 JSON 余额。再加上我加了@JsonProperty(acccess = Access.READ_ONLY)
来平衡。有人请帮助我已经坚持了这么多小时。
更新
解决了。请参阅下面的解决方案。
RESTCONTROLLER 上的单元测试帖子请求更新
我设法解决了这个错误,总而言之,这是因为我将一个对象传递给模拟服务一个不同的内存地址。简单来说,
when(userService.updateUserBalance(1, userAmountDTO)).thenReturn(userAmountDTO);
,这是模拟 userService.updateUserBalance 方法的合适方式。
但是, 在
@Test
中,userAmountDTO 内存地址可能类似于@21835tj3。在我的控制器 userAmountDTO = userService.updateUserBalance(userId, userAmountDTO);
中,传递给 userService.updateUserBalance
方法的 userAmountDTO 的内存地址可能与 @21943jf3 不同,这就是它与单元测试中的模拟服务参数不匹配的原因。具有相同字段和值的对象并不意味着它们共享相同的引用,因此模拟方法没有返回预期值。
解决这个问题:
使用
ArgumentMatchers.any()
Mockito 来匹配UserAmountDTO
类的任何对象。因此,将单元测试中的模拟方法更改为when(userService.updateUserBalance(1, ArgumentMatchers.any(UserAmountDTO))).thenReturn(userAmountDTO);
希望这可以帮助任何为此苦苦挣扎的人!当我们传入反序列化的 JSON 对象时,它通常发生在 POST 请求中。还要感谢@JorgeCampos 对调试过程的支持。