문제 발생 (1)
java.lang.NullPointerException: Cannot invoke "org.springframework.test.web.servlet.ResultActions.andDo(org.springframework.test.web.servlet.ResultHandler)" because the return value of "org.springframework.test.web.servlet.MockMvc.perform(org.springframework.test.web.servlet.RequestBuilder)" is null
문제의 코드
@WebMvcTest(controllers = OrderController.class)
class OrderControllerTest {
@MockBean
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private OrderService orderService;
@DisplayName("신규 주문을 등록한다.")
@Test
void createOrder() throws Exception {
// given
OrderCreateRequest request = OrderCreateRequest.builder()
.productNumbers(List.of("001"))
.build();
// when & then
mockMvc.perform(
post("/api/v1/orders/new")
.content(objectMapper.writeValueAsString(request))
.contentType(APPLICATION_JSON)
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value("200"))
.andExpect(jsonPath("$.status").value("OK"))
.andExpect(jsonPath("$.message").value("OK"));
}
}
- 문제점이 뭔지 디버깅도 돌려보고, 확인을 해봤는데 ..
- mockMvc.perform이 ResultActions를 반환하는데 자꾸 null값이 뜨는 현상이였다.
해결책
- 그래서 찾아봤는데 내가 MockMvc를 @MockBean -> 가짜 객체로 등록한 상황이였다.
- @Autowired를 붙여 기능을 사용할 수 있게 되었다. (허무)
문제 발생 (2)
java.lang.AssertionError: Status expected:<400> but was:<200>
Expected :400
Actual :200
문제의 코드
@Getter
public class OrderCreateRequest {
@NotEmpty(message = "상품 번호 리스트는 필수입니다.")
private List<String> productNumbers;
}
@DisplayName("신규 주문을 등록할 때 상품번호는 1개 이상이어야 한다.")
@Test
void createOrderWithEmptyProductNumbers() throws Exception {
// given
OrderCreateRequest request = OrderCreateRequest.builder()
.productNumbers(List.of())
.build();
// when & then
mockMvc.perform(
post("/api/v1/orders/new")
.content(objectMapper.writeValueAsString(request))
.contentType(APPLICATION_JSON)
)
.andDo(print())
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("400"))
.andExpect(jsonPath("$.status").value("BAD_REQUEST"))
.andExpect(jsonPath("$.message").value("상품 번호 리스트는 필수입니다."))
.andExpect(jsonPath("$.data").isEmpty());
}
- 사실 문제점이 없다.
- 근데 빈 리스트를 반환하면 @NotEmpty 어노테이션이 validation을 해주면서 RestControllerAdvice의 BindResult에 Exception이 담겨서 커스텀 응답을 return하게 된다. 400 Bad Request를 리턴하도록 설정해두었다.
- 근데 200 OK 응답이 오는게 문제였다.
해결책
@PostMapping("/api/v1/orders/new")
public ApiResponse<OrderResponse> createOrder(@RequestBody OrderCreateRequest request) {
LocalDateTime registeredDateTime = LocalDateTime.now();
return ApiResponse.ok(orderService.createOrder(request, registeredDateTime));
}
- 뭔가 이상한 점을 느끼셨을 것이다.
- @ReuquestBody 앞에 @Valid를 넣어주는 것을 까먹었다. (!) ㅠㅠ