Springboot 에서 test code 작성하기 시리즈
- Springboot 에서 test code 작성하기 1편 - 통합테스트(MVC)
- Springboot 에서 test code 작성하기 2편 - assetThat이 중복되는 테스트와 Spock
최근사내 프로젝트에서 테스트 코드를 작성하고자 생각했습니다.
목표는 해당 컨트롤러의 메소드가 잘 동작하는지(요청을 잘 보내고 예상한 응답을 잘 받는지), 서비스가 개별적으로 잘 동작하는지 확인하는 것 입니다.
컨트롤러는 운영 환경과 비슷하게 테스트 하기 위해 통합 테스트
, 서비스는 의존성을 줄이고 해당 서비스의 목표에만 집중하기 위해 단위테스트
를 하기로 결정했습니다.
테스트에 관한 글을 찾아보던 중 우아한형제들 기술블로그에서 테스트 메소드의 이름을 한글로 짓는다는 것을 알게 되었습니다.
테스트가 실패했을 때 어느 기능에서 오류가 났는지 직관적으로 알 수 있어 좋은 것 같아서 테스트 메소드 명을 한글로 작성했습니다.
1. MVC 컨트롤러 통합 테스트
목표는 고객 정보를 조회 및 등록하는 메소드를 통합테스트 하는 것 입니다.
컨트롤러 통합 테스트는 클래스 상단에 @SpringbootTest
을 선언합니다.
모든 Bean을 올리는 것으로 다른 테스트에 비해 테스트 시간이 오래 소요되지만 운영환경과 비슷하게 테스트 할수 있습니다.
선언한 어노테이션은 다음과 같습니다:
어노테이션 | 설명 |
---|---|
@RunWith(SpringRunner.class) | 테스트를 실행하기 위해 참조하는 클래스(SpringRunner) |
@AutoConfigureWebMvc | MVC와 관련된 Bean을 올린다 |
@Transactional | 테스트 후 DB 롤백 |
@Ignore | 실제로 실행할 필요가 없기 때문에 Ignore를 선언 |
@SpringBootTest | 모든 Bean을 올리는 통합 테스트 |
1 | /** |
@SpyBean
은 해당 객체를 주입받아 사용하다 given을 주면 선언한 해당 기능으로 동작하는 Bean 입니다.
해당 어노테이션은 [SpringBoot @MockBean, @SpyBean 소개] 포스팅에서 더 자세히 알 수 있습니다.
고객정보를 조회 및 등록하는 메소드가 있는 도메인 인 CustomerController
가 있습니다.
아래 코드는 예시입니다.
1 |
|
코드상엔 없지만 CustomerController
의 모든 메소드의 session과 header에는 특정 값이 셋팅되어 있어야 한다고 가정합니다.
따라서 위 getCustomerList
를 테스트 하는 코드는 다음과 같습니다:
1 | //테스트 수행시 실행 |
그 밖에도 param()
등 으로 파라미터를 넘길수도 있습니다.
이렇게 Controller를 통합테스트 를 실행해 전체 플로우를 테스트 할 수 있습니다.
@SessionAttributes
를 사용하는 방법도 있는데 이 경우엔 테스트 코드에서 requestAttr()
대신 sessionAttr()
을 사용할 수 있습니다.
이 방법은 이곳의 예제로 확인할 수 있습니다.
만약
1 | "") ( |
이렇게 DTO에 @RequestBody
가 없는 도메인을 테스트하려면 조금 복잡해집니다.
저의 경우, 회사 코드의 POST 도메인 파라미터 DTO에 일부 @RequestBody
가 없었고, @RequestBody
를 추가 할 경우 문제가 생길 수 있었기 때문에
기존 코드를 변경하지 않고 테스트 하는 방법을 찾아보았습니다.
우선 Spring에서는 권장하지 않습니다 그 이유는 다음과 같습니다.
통합 테스트의 주 목적 중 하나는 MockMvc 모델 객체가 Object 데이터로 바뀌었는지 확인하는 것 입니다.
NewObject(DTO)를 자동으로 변환하면 NewObject(DTO)가 실제 form과 호환되지 않는 문제가 있는데, 이러한 문제가 있는 파라미터는 테스트에서 제외되기 때문에 NewObject(DTO)는 Null이 됩니다.
그래서 @RequestBody
가 없는 도메인의 DTO 파라미터는 십중팔구 넘어가지 않으며 null이 됩니다.
이것을 해결하기 위한 방법은 두가지 정도가 있습니다.
HttpClient 사용
1 |
|
buildUrlEncodedFormEntity() 이용
1 |
|
위와 같이 작성하시면 NewObject(DTO)에 값이 셋팅되어 파라미터로 잘 전달되는 것을 확인할 수 있습니다.
관련 내용은 Testing Form posts through MockMVC에서 더 자세히 알아보실수 있습니다.
위 시리즈는 2부로 나뉘어 통합테스트, spock를 사용한 테스트로 작성 될 예정입니다.
많이 미숙하지만 지속적으로 알아가고 있습니다.
혹 틀린 부분 혹은 궁금한 점이 있다면 코멘트로 남겨주세요. 읽어주셔서 감사합니다🙏
참고자료