본문 바로가기

프로젝트/멋사 개인 프로젝트 (mutsa-SNS)

[04] mutsa-SNS 2일차 - (1) 회원가입 test code

회원가입 controller의 test code를 추가하였다.

회원가입 성공, 실패 두가지 case에 대해 실행하였다.

 

1. TestCode

UserControllerTest

@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    MockMvc mockMvc;

    @MockBean
    UserService userService;

    @Autowired
    ObjectMapper objectMapper;

    @Test
    @DisplayName("회원가입 성공")
    @WithMockUser
    void join_success() throws Exception{
        UserJoinRequest userJoinRequest = UserJoinRequest.builder()
                .userName("haneul")
                .password("1234")
                .build();

        when(userService.join(any())).thenReturn(mock(UserDto.class));

        mockMvc.perform(post("/api/v1/users/join")
                .with(csrf())
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsBytes(userJoinRequest)))
                .andDo(print())
                .andExpect(status().isOk());

    }

    @Test
    @DisplayName("회원가입 실패 - userName 중복")
    @WithMockUser
    void join_fail() throws Exception{
        UserJoinRequest userJoinRequest = UserJoinRequest.builder()
                .userName("haneul")
                .password("1234")
                .build();

        when(userService.join(any()))
                .thenThrow(new AppException(ErrorCode.DUPLICATED_USER_NAME, ""));

        mockMvc.perform(post("/api/v1/users/join")
                        .with(csrf())
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsBytes(userJoinRequest)))
                .andDo(print())
                .andExpect(status().isConflict());
    }
}

 

Layered architecture에서 controller는 service를 의존하고, service는 repository를 의존하고 있기 때문에, test code에서 controller를 불러와 test를 하고 싶으면 service와 repository를 다 불러와야된다.

-> unit test 성립이 안되고, test 실행 시간도 길어지고, db dependency가 생기게 된다.

-> test의 원칙에 잘 맞지 않게 된다.

따라서 Mock을 이용한다.

  • Mock : 가짜 객체. service (ex findById(id))가 실행되었다 가정하고, return값을 넣어준다. 빠르게 고립된 테스트가 가능하다.

 

MockMvc에 요청한 응답에 대하여 expect가 모두 통과하면 test success.

실패시 해당하는 httpStatus가 나오는지와, 성공시 status가 200이 나오는지 test해본다.

  • .writeValueAsBytes : Object를 JSON으로 만들어 준 후, byte 배열로 반환해준다.
  • @WebMvcTest : @SpringBootTest은 모든 bean을 불러오기 때문에 시간이 오래 걸리고, test 단위가 크다. 따라서 controller만을 test하고 싶을 때, 위의 annotation을 이용한다.
  • @MockBean : 가짜 객체를 생성하여 주입힌다. 이 test에는 service를 선언하기 위해 사용하였다. service와의 dependency를 걱정할 필요가 없다.
  • MockMvc : 배포하지 않고도, 서버의 MVC 동작을 테스트 할 수 있는 라이브러리이다.
  • perform : 요청을 전송하는 역할.
  • get : HTTP method( get(), post(), put(), delete() )를 결정할 수 있다. 통신의 경로를 지정해 준다.
  • andExpect() : 응답을 검증하는 method이다.
  • andDo(print()) : 요청/응답 전체 메세지를 확인.

<전체 Reference>

https://ykh6242.tistory.com/entry/MockMvc%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-REST-API%EC%9D%98-Json-Response-%EA%B2%80%EC%A6%9D

 

MockMvc를 이용한 REST API의 Json Response 검증

MockMvc를 이용하여 API의 Json Response를 JsonPath 표현식을 사용해 검증하는 예제를 정리하였습니다. 테스트 예제를 보기 앞서 테스트에 필요한 기본적인 지식들을 간단히 서술 해보겠습니다. 의존성

ykh6242.tistory.com

https://shinsunyoung.tistory.com/52

 

SpringBoot의 MockMvc를 사용하여 GET, POST 응답 테스트하기

안녕하세요! 이번 포스팅에서는 SpringBoot 프레임워크에서 제공해주는 MockMvc를 만들고 테스트하는 방법을 알아보도록 하겠습니다. 전체 코드는 Github에서 확인이 가능합니다. ✍️ 📚 개념 정리 1

shinsunyoung.tistory.com

https://gom20.tistory.com/123

 

[Spring Boot] Controller 단위 테스트 (@WebMvcTest, MockMvc)

@WebMvcTest Application Context 완전하게 Start 시키지 않고 web layer를 테스트 하고 싶을 때 @WebMvcTest를 사용하는 것을 고려한다. Present Layer 관련 컴포넌트만 스캔을 한다. Service, Repository dependency가 필요한

gom20.tistory.com