Java - 单元测试中响应 JSON 的输出不正确

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

我正在测试我的 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)
来平衡。有人请帮助我已经坚持了这么多小时。

更新

解决了。请参阅下面的解决方案。

java spring-boot unit-testing
1个回答
0
投票

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 对调试过程的支持。

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