최근에 Java를 이용한 웹 애플리케이션 프로젝트를 진행할 때는 Spring을 때 놓고 생각할 수 없다. JUnit에서는 Extension Model을 이용해서 다른 시스템과의 연결이 가능한데 연동이 되어야 Spring Framework와 소통하며 @Autowired등을 통해 빈을 사용할 수 있다.
이번 포스트에서는 Spring Framework와 JUnit을 연동하는 방법에 대해 살펴보자.
JUnit의 @ExtendWith는 Junit과 다른 프레임워크와의 연동을 지원한다. 당연히@ExtendWith(SpringExtension.class)는 JUnit과 Spring을 연동하기 위해 사용되는 애너테이션이다. 이 둘이 연동되면 @Autowired 등 애너테이션을 테스트에서 사용할 수 있다. @ContextConfiguration을 이용해서설정 파일을 연결하면 로드된 빈은 injection 받아 사용할 수 있다.
하지만 SpringBoot는 테스트에 대해서도 다양한 자동화 설정을 만들어두어 보다 편리하게 테스트를 진행할 수 있게 되었다.
@SpringBootTest
SpringBoot에서 단위테스트를 위해서는@SpringBootTest를 사용할 수 있다. @SpringBootTest는 @SpringBootApplication 클래스를 이용해 ApplicationContext를 로딩하기 때문에 별도로 @ContextConfiguration을 추가할 필요는 없다.
매우 간편해졌는데 단점은 @SpringBootTest는 단위 테스트가 아니라 통합 테스트이기 때문에 일부분만 테스트하려는 상황에서 많은 부담이 된다. 예를들어 단순히 MVC의 URL을 처리하는 Controller를 테스트 하고 싶은데 Database까지 실행해야 하거나 반대로 JPA가 잘 동작하는지 테스트 해보고 싶은데 웹 계층까지 고려해야 한다면 속도도 매우 느려지고 테스트 실패의 원인을 분석하기도 어려워진다.
따라서필요한 구성 부분들만 로딩해서 처리할 수 있게 해주는데 이런 형태의 테스트를Slice Test라고 한다.
Slice Test
SpringBoot에서는 @XXTest 애너테이션을 이용해서 다양한 Slice Test를 지원한다. 다음페이지에서 Slice Test관련 애너테이션들과 사용 시 자동으로 설정되는 환경들을 확인할 수 있다.
MockMvc 객체가 자동으로 구성되어 테스트가 용이하다(@SpringBootTest에서는 @AutoConfigureMockMvc 추가 필요)
추가적으로 필요한 설정이 있다면 @Import를 이용할 수 있다.
@DataJpaTest
@Entity와 Spring Data JPA Repository 타입의 빈들을 자동 구성한다.
embedded database를 자동으로 구성하고 테스트에 사용할 수 있다.
spring.jpa.show-sql 자동 설정으로 sql 문장을 로깅한다.
모든 테스트 마다 rollback이 자동으로 진행된다.
테스트를 위해 TestEntityManager를 주입받아서 사용할 수 있다.
@RestClientTest
RestTemplate등을 이용해서 원격의 서버와 통신하는 Service를 테스트 하기 위해 사용된다.
RestTemplateBuilder, RestClient.Builder가 자동 주입 된다.
테스트에서 MockRestServiceServer를 이용해서 서버를 Mocking 할 수 있다.
테스트하려는 대상 빈은 value 또는 components 속성으로 지정할 수 있다.
아울러 로딩에서 제외된 빈에 대한 Mock이 필요한 경우는 @MockBean이나 @SpyBean을 사용한다.
spring boot 테스트 주의 사항?(기본 사항)
가끔 spring boot로 테스트 하는 과정에서 아래와 같은 오류를 만날 때가 있다.
java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use
@ContextConfiguration or @SpringBootTest(classes=...) with your test
@SpringBootTest는 @SpringBootApplication이 붙은 클래스와 같은 패키지에 두어야 한다.
즉 좌측의 구조 처럼 @SpringBootApplication이 com.quietjun.junittest에 있을 때 com.quietjun.junittest.JunitApplicationTest는 정상적으로 동작하지만 mvc.JunitApplicationTest는 오류를 발생시킨다.