【问题标题】:How to Controller Layer Test feat simple code example如何控制器层测试壮举简单代码示例
【发布时间】:2021-01-05 14:27:50
【问题描述】:

代码:https://github.com/mijosan/test-practice/tree/master/mybatis

@RequiredArgsConstructor
@RestController
public class UserController {

  private final UserService userService;

  @PostMapping(value="/v1/user")
  public ResponseEntity<ResponseDto> postUser(@RequestBody UserSaveRequestDto userSaveRequestDto) {
      Long userId = userService.insertUser(userSaveRequestDto);

      return CommonUtil.getResponseEntity(UserResponseDto.builder()
                                                              .userId(userId)
                                                              .build()
                                                              , HttpStatus.OK
                                                              , "회원 등록 완료");
  }

}

这是我的测试代码

@WebMvcTest
public class UserControllerTest {

  @Autowired
  MockMvc mockMvc;

  @Autowired
  ObjectMapper objectMapper;

  @MockBean
  UserService userService;

  UserSaveRequestDto userSaveRequestDto;

  @BeforeEach
  void setUp() {
      userSaveRequestDto = UserSaveRequestDto.builder()
          .userName("test")
          .userPhoneNumber("01026137832")
          .build();
  } 

  @DisplayName("MockMvc를 이용한 postUser slice 테스트")
  @Test
  public void postUserTest() throws Exception {
      // given
      given(userService.insertUser(userSaveRequestDto)).willReturn(1L);
      String content = objectMapper.writeValueAsString(userSaveRequestDto);

      // when
      MvcResult mvcResult = mockMvc.perform(post("/v1/user")
                      .contentType(MediaType.APPLICATION_JSON)
                      .content(content))
                          .andExpect(status().isOk())
                          .andReturn();
    
      // then
      String result = mvcResult.getResponse().getContentAsString();

      System.out.println(result);
  }

}

我收到“java.lang.AssertionError: Status expected: but was:”的异常

但是,如果你大摇大摆地测试它,它会很好。

原因在哪里?

【问题讨论】:

    标签: java spring-boot unit-testing junit tdd


    【解决方案1】:

    如果你修改你的测试代码

    ...
    .content(content))
        .andDo(result -> {
            result.getResolvedException().printStackTrace();
        })
        .andExpect(status().isOk())
    ...
    

    你会在日志中找到

    org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class com.example.mybatis.dto.ResponseDto
        at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:220)
        at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:219)
        at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:124)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
    ....
    

    500 的原因是控制器无法序列化您的ResponseDto。您需要在您的ResponseDto 上添加lombok.Getter。

    【讨论】:

    • 但我还有一个问题。 ResponseDto是使用Builder模式创建的,什么时候使用Get方法?
    • Spring中ObjectMapper的默认配置是:对象序列化(object to String)使用getter,对象反序列化(String to object)使用setter。在您的情况下,您缺少吸气剂。
    • 该代码中当前序列化发生在哪一行?
    • 您可以在查看我在答案中提到的完整异常时看到它。简而言之:当您的某些控制器函数返回一些值并且该函数具有注释@ResponseBody 时,Spring 将获取返回值并将其序列化为 JSON(当它是对象而不是原语时)并将其返回给您的 REST 客户端.在您的情况下, ResponseBody 取自 RestController 注释并应用于控制器类的所有功能。
    • 天哪……我忘记了……我能再问你一个问题吗? “给定(userService.insertUser(userSaveRequestDto)).willReturn(1L);”返回 0 而不返回 1L。为什么?,,,这是最后一个问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    相关资源
    最近更新 更多