Springboot 에서 test code 작성하기 시리즈
- Springboot 에서 test code 작성하기 1편 - 통합테스트(MVC)
- Springboot 에서 test code 작성하기 2편 - 단위테스트(Service)
- Springboot 에서 test code 작성하기 3편 - assetThat이 중복되는 테스트와 Spock
최근 사내 프로젝트에 테스트 코드를 작성할 기회가 있었다.
컨트롤러는 운영 환경과 비슷하게 테스트 하기 위해 통합 테스트, 서비스는 의존성을 줄이고 해당 서비스의 목표에만 집중하기 위해 단위테스트를 하기로 결정했다.
목표는 해당 컨트롤러의 메소드가 잘 동작하는지(요청을 잘 보내고 예상한 응답을 잘 받는지), 서비스가 개별적으로 잘 동작하는지 확인하는 것 이다.
테스트에 관한 글을 찾아보던 중 우아한형제들 기술블로그에서 테스트 메소드의 이름을 한글로 짓는다는 것을 알게 되었다.
테스트가 실패했을 때 어느 기능에서 오류가 났는지 직관적으로 알 수 있어 좋은 것 같아서 테스트 메소드 명을 한글로 작성했다.
1. MVC 컨트롤러 통합 테스트
목표는 고객 정보를 조회 및 등록하는 메소드를 통합테스트 하는 것 이다.
컨트롤러 통합 테스트는 클래스 상단에 @SpringbootTest
을 선언한다.
모든 Bean을 올리는 것으로 다른 테스트에 비해 테스트 시간이 오래 소요되지만 운영환경과 비슷하게 테스트 할 수 있다.
따라서 클래스에 선언한 어노테이션은 다음과 같다.
어노테이션 | 설명 |
---|---|
@RunWith(SpringRunner.class) | 테스트를 실행하기 위해 참조하는 클래스(SpringRunner) |
@AutoConfigureWebMvc | MVC와 관련된 Bean을 올린다 |
@Transactional | 테스트 후 DB 롤백 |
@Ignore | 실제로 실행할 필요가 없기 때문에 Ignore를 선언 |
@SpringBootTest | 모든 Bean을 올리는 통합 테스트 |
1 | /** |
@SpyBean
은 해당 객체를 주입받아 사용하다 given을 주면 선언한 해당 기능으로 동작하는 Bean 이다.
고객정보를 조회 및 등록하는 메소드가 있는 도메인 인 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과 호환되지 않는 문제가 있는데, 이러한 문제가 있는 파라미터는 테스트에서 제외되기 때문이다.
그래서 @RequestBody
가 없는 도메인의 DTO 파라미터는 십중팔구 넘어가지 않으며 null이된다.
이것을 해결하기 위한 방법은 두가지 정도가 있다.
HttpClient 사용
1 |
|
buildUrlEncodedFormEntity() 이용
1 |
|
Testing Form posts through MockMVC에서 더 알아볼 수 있다.
위 시리즈는 3부로 나뉘어 통합테스트, 단위테스트, spock를 사용한 테스트로 작성 될 예정입니다.
많이 미숙하지만 지속적으로 알아가고 있습니다.
혹 틀린 부분 혹은 궁금한 점이 있다면 댓글 부탁드리겠습니다 읽어주셔서 감사합니다!🙏
참고자료