오랜만에 테스트 코드를 작성하기 위해 구글링 해서 작성을 했는데 내가 짜 놓은 시나리오대로 동작을 하지 않아 더 구글링, 그리고 주변에 사람들에게 질문을 하였지만.... 해답은 안 보였다.
작성한 테스트 코드는 아래와 같다.
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;
}
구글링 해도 해도 안나오는 문제인데, 혹시나 나처럼 삽질하는 사람들을 위해 기록해 둔다.
'Java > Spring' 카테고리의 다른 글
API 호출 테스트를 위한 간단한 팁 (0) | 2020.12.21 |
---|---|
AttributeConverter class registered multiple times 에러가 발생할 경우 (0) | 2020.12.16 |
Springboot + JPA + JTA (Atomikos) + MySQL 을 이용한 멀티 트랜잭션 구현 (0) | 2019.12.05 |
멀티 DataSource 접속 방법 정리 (0) | 2019.08.13 |
Spring Batch, Migration, 튜닝 및 OOM 해결 후기 (0) | 2019.08.12 |