Java/Spring

테스트 코드 작성 시 willReturn 값이 안나오는 경우

체리필터 2020. 12. 2. 17:08
728x90
반응형

오랜만에 테스트 코드를 작성하기 위해 구글링 해서 작성을 했는데 내가 짜 놓은 시나리오대로 동작을 하지 않아 더 구글링, 그리고 주변에 사람들에게 질문을 하였지만.... 해답은 안 보였다.

작성한 테스트 코드는 아래와 같다.

 

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;

import java.util.HashMap;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(BankAccountApiController.class)
public class BankAccountApiControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean(name = "bankAccountApiService")
    private BankAccountApiService bankAccountApiService;

    @Test
    public void testCheck() throws Exception {
        CooconBankAccountDto cooconBankAccountDto = cooconBankAccountDtoBuilder();
        CooconBankAccountResponseDto cooconBankAccountResponseDto = cooconBankAccountResponseDtoBuilder();

        given(bankAccountApiService.check(cooconBankAccountDto)).willReturn(cooconBankAccountResponseDto);

        final ResultActions resultActions
                = mockMvc.perform(
                        get("/api/bank-accounts")
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                        .header("X-API-VERSION", "1.0.0")
                        .param("bankCd", "bankCd")
                        .param("acctNm", "acctNm")
                        .param("searchAcctNo", "searchAcctNo")
                )
                .andDo(print());

        resultActions
                .andExpect(status().isOk())
                .andExpect(jsonPath("data.check").value(YNType.Y.value()))
        ;
    }

    private CooconBankAccountDto cooconBankAccountDtoBuilder() {
        CooconBankAccountDto cooconBankAccountDto = new CooconBankAccountDto();
        cooconBankAccountDto.setBankCd("bankCd");
        cooconBankAccountDto.setAcctNm("acctNm");
        cooconBankAccountDto.setSearchAcctNo("searchAcctNo");

        return cooconBankAccountDto;
    }

    private CooconBankAccountResponseDto cooconBankAccountResponseDtoBuilder() {
        CooconBankAccountResponseDto cooconBankAccountResponseDto = new CooconBankAccountResponseDto();
        cooconBankAccountResponseDto.setCheck(YNType.Y.value());

        return cooconBankAccountResponseDto;
    }
}

 

위와 같이 하고 테스트를 돌렸는데 willReturn에 선언해 줬던 값이 null 로 반환되어졌고, 결국 andExpect(jsonPath("data.check").value(YNType.Y.value())) 값이 실패로 떨어지게 되었다.

이 말은 Mock 객체인 bankAccountApiService 가 제대로 동작하지 않는다는 것을 의미 하였다.

 

willReturn과 andExpect 동작을 확인해 보기 위해 임시 메소드를 bankAccountApiService 안에 만들고 테스트를 해 보니 정상적으로 동작 하였다.

 

따라서 테스트 코드 작성을 위한 기본 라이브러리들의 문제는 아니였다.

 

이러 저러한 소스 수정과 테스트를 계속 하던 중 특이점을 발견하였고 문제는 lombok에 있음을 알게 되었다.

check 메소드 안에 넣어주던 CooconBankAccountDto 선언을 아래와 같이 한 것이 문제였다.

 

import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.*;

@Getter
@Setter
@JsonNaming(UpperCaseUnderscoreStrategy.class)
public class CooconBankAccountDto {

    private String bankCd;

    private String acctNm;

    private String searchAcctNo;

    private String trscSeqNo;

    private String check;
}

lombok 에서 Genrate 해주는 메소드들 중에서 Getter, Setter만 두었었는데 테스트시 필요한 다른 메소드들이 있어야 했다.

정확히 어떤 Annotation인지 알 수 없어서 @Data를 사용해서 테스트 해 보니 테스트 통과!

 

정확히 어떤 것 때문에 문제인지 확인하고자 @Data를 제거하고 lombok에서 제공해 주는 다른  Annotation 이를테면 @AllArgsConstructor, @NoArgsConstructor 등을 넣어가며 테스트 했지만 테스트 실패...

결국 찾게 된 것은 @EqualsAndHashCode 였다.

아래와 같이 수정하니 테스트는 성공 하였다.

import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.*;

@Getter
@Setter
@EqualsAndHashCode
@JsonNaming(UpperCaseUnderscoreStrategy.class)
public class CooconBankAccountDto {

    private String bankCd;

    private String acctNm;

    private String searchAcctNo;

    private String trscSeqNo;

    private String check;
}

 

구글링 해도 해도 안나오는 문제인데, 혹시나 나처럼 삽질하는 사람들을 위해 기록해 둔다.

728x90
반응형