인프런 커뮤니티 질문&답변

박용관님의 프로필 이미지

작성한 질문수

Practical Testing: 실용적인 테스트 가이드

Presentation Layer 테스트 (2)

컨트롤러 테스트 시 POST시 Mockito.when() 처리에서 질문드립니다.

24.06.06 23:40 작성

·

130

1

안녕하세요 제가 좀 더 응용해서 post 요청 시에 Mockito.when()과 접목시킨 테스트를 진행해봣는데 이 과정에서 질문이 있어 질문 드립니다.

 

예시 코드는 다음과 같습니다.

void signUpTest() throws Exception {
    //given
    var memberResponse = new MemberResponse(MEMBER_ID, MEMBER_EMAIL);
    var signUpRequest = new SignUpRequest(MEMBER_EMAIL, "password");

    //when
    when(memberFacadeService.signUp(signUpRequest))
            .thenReturn(memberResponse);

    //then
    mockMvc.perform(
                    post("/api/v1/members/signUp")
                            .content(OBJECT_MAPPER.writeValueAsString(signUpRequest))
                            .contentType(MediaType.APPLICATION_JSON)
            )
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id").value(MEMBER_ID))
            .andExpect(jsonPath("$.email").value(MEMBER_EMAIL));
}


이 코드 시에 문제가 발생합니다. 문제는 java.lang.AssertionError: No value at JSON path "$.id"

이거입니다.

 

근데, 이 코드를 아래와 같이 바꾸면 에러가 발생하지 않습니다.

void signUpTest() throws Exception {
    //given
    var memberResponse = new MemberResponse(MEMBER_ID, MEMBER_EMAIL);
    var signUpRequest = new SignUpRequest(MEMBER_EMAIL, "password");

    //when
    when(memberFacadeService.signUp(any(SignUpRequest.class))) 
            .thenReturn(memberResponse);

    //then
    mockMvc.perform(
                    post("/api/v1/members/signUp")
                            .content(objectMapper.writeValueAsString(signUpRequest))
                            .contentType(MediaType.APPLICATION_JSON)
            )
            .andDo(print())
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id").value(MEMBER_ID))
            .andExpect(jsonPath("$.email").value(MEMBER_EMAIL));
}


위와 아래의 차이는 requestBody에 들어가는 SignUpRequest 클래스를 mockBean처리 된 memberFacadeService의 when 처리 시에 해당 클래스를 any()로 처리하나 안처리하나의 차이입니다.

 

제가 예상하기에는 mockMvc에서 .content(objectMapper.writeValueAsString(signUpRequest)) 로 이렇게 처리했기 때문에 해당 로직에 들어가는 memberFacadeService 클래스의 signUp 매개변수로 들어가는 SignUpRequest가 제가 위에서 선언한 signUpRequest와 다르기 때문에 발생하는 문제라고 생각합니다.

 

이 이해가 맞는지에 대한 질문과 post요청에서는 다 이렇게 any()처리를 해야되는지 궁금합니다.

 

답변 1

1

박우빈님의 프로필 이미지
박우빈
지식공유자

2024. 06. 08. 11:46

안녕하세요, 박용관 님!

네, 맞습니다. 말씀하신 것처럼 위쪽의 mocking 로직은 특정 인스턴스에만 해당하는 mocking이기 때문에, 직렬화/역직렬화 과정을 거쳐 다시 만들어진 인스턴스는 이전에 만들었던 signUpRequest와 다른 인스턴스이기 때문에 그렇습니다.

그렇기에 아래쪽에 해주신 것처럼 특정 타입(SignUpRequest.class)에 모두 해당하는 mocking이 되도록 any()로 처리해주는 것이 맞습니다.

post 요청이라 any() 처리를 한다기 보다는, mocking하는 상황에 맞게 처리해야 한다, 로 이해하시는 것이 좋을 것 같아요 ㅎㅎ

도움이 되셨기를 바랍니다.
감사합니다. 🙂