====== SpringBoot Test ====== * [[springframework:springboot|SpringBoot]] Test * [[java:junit:5|JUnit 5]] * [[springframework:springboot:mvc|SpringBoot and Spring MVC]] * [[springframework:springboot:webmvctest|SpringBoot WebMvcTest]] * [[https://docs.spring.io/spring-boot/docs/current/reference/html/test-auto-configuration.html|Test Auto-configuration Annotations]] / [[https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure|Spring Boot Test Autoconfigure]] 여기에서 각종 test 자동화 Annotation을 확인할 수 있다. ===== @SpringBootTest ===== * 기본적인 SpringBoot 통합 테스트 어노테이션. * 이 안에 들어가면 ''@ExtendWith(SpringExtension.class)''가 함께 지정되어 있어서 JUnit 5에서 자동 수행된다. * ''@ExtendWith(SpringExtension.class)'' 는 SpringBoot 2.1 부터 ''@SpringBootTest'' 와 그 하위 애노테이션(''@DataJpaTest'' 등)에 기본 내장돼 있으므로 테스트 클래스에 지정할 필요가 없다. ==== @SpringBootApplication 클래스 탐지 ==== * ''@SpringBootTest'' 는 이 애노테이션이 지정된 클래스보다 아래에 있거나 동일 패키지 경로상의 상위 패키지에 존재하는 ''@SpringBootApplication'' 클래스도 자동 탐지한다. * ''classes={}'' 로 명시할 수도 있다. ==== 테스트용 프라퍼티 지정 ==== @SpringBootTest(properties = {"some.username=user", "some.password=pwd"}, webEnvironment = SpringBootTest.WebEnvironment.NONE) ==== Context Cache ==== * 기본적으로 Application Context 를 Cache 한다. * 하지만 일부 테스트의 설정에서 [[https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/mock/mockito/MockBean.html|@MockBean]], [[https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/mock/mockito/SpyBean.html|@SpyBean]] 등을 사용하면 컨텍스트가 오염되므로 새로운 컨텍스트가 생성되고 또 캐시 된다. * 이로인해 성능저하가 심해질 수 있으므로 되도록 컨텍스트를 하나 혹은 최소한의 공통으로 유지하는 것이 중요하다. * 캐시를 한다는 뜻은 새로운 컨텍스트를 생성해야 하는 상황에서 기존 컨텍스트를 그대로 유지하는 것이다. * 즉, DB 접속등이 이뤄지는 컨텍스트의 경우 connection pool 로 인해서 DB 서버의 커넥션 수가 꽉차는 상황이 발생할 수 있다. * **Test 용 설정에서 Connection Pool의 min 사이즈는 작게 잡는게 좋다** * [[https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/context/cache/DefaultContextCache.html|DefaultContextCache]] : 기본 컨텍스트 캐시 구현체 ''spring.test.context.cache.maxSize'' 프라퍼티에 **''mb''** 단위로 지정. # 32mb 기본값 spring.test.context.cache.maxSize=32 ==== @TestConfiguration ==== * [[https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/context/TestConfiguration.html|@TestConfiguration]] * Test 용 ''@Configuration'' * [[https://reflectoring.io/spring-boot-testconfiguration/|Testing with Spring Boot's @TestConfiguration Annotation]] * 기존 Bean 설정을 override 하거나 더 추가한다. * ''@Configuration'' 은 component scan 으로 자동으로 탐지되지만 ''@TestConfiguration'' 은 자동탐지를 하지 않고 ''import'' 명시할 때만 작동한다. 테스트시 오작동을 줄일 수 있다. * 혹은 ''@SpringBootTest'' 가 지정된 클래스의 ''static'' inner class 로 만들어 지정하면 자동 탐지한다. * Test 시에는 기존 bean 을 override 해야 할 수 있기 때문에 관련 프라퍼티를 지정한다. 가급적 production 코드에서는 ''false''로 둬야한다. spring.main.allow-bean-definition-overriding=true ==== Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test ==== * ''Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test'' 라는 오류가 발생한다면 ''@SpringBootApplication'' 애노테이션이 붙은 클래스가 존재하는 패키지의 하위 패키지에 테스트를 둬야 한다는 원칙을 어긴 것이다. * 예: ''a.b.c.Application'' 이라면, 테스트 클래스는 ''a.b.c'' 아래의 패키지에 존재해야한다. 만약 ''a.b.**x**'' 처럼 돼있는 패키지에 테스트 클래스가 존재하면 자동으로 ''@SpringBootApplication''을 탐색하지 못한다. * **보통 ''@SpringBootApplication''이 존재하지않는 Library 성 모듈**의 경우 발생한다. === 해결 1 === * 테스트에 **''@EnableAutoConfiguration''** 추가, * 테스트 ''resources''에 ''application.yml'' 필요(혹은 명시적 지정) * ''@SpringBootTest(classes = config 클래스 목록 지정)'' @SpringBootTest(classes = MyServiceConfig.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) @EnableAutoConfiguration class MyApplicationTests { } === 해결 2 === * 테스트 소스에 동일 패키지에 ''@SpringBootApplication'' 이 붙은 클래스를 하나 만들어주면 된다. 패키지만 동일하다면 ''classes''지정 불필요. * 패키지 구조가 다르면 ''classes''에 해당 ''@SpringBootApplication''이 붙은 클래스를 지정해도 된다. * 테스트 ''resources''에 ''application.yml'' 필요(혹은 명시적 지정) @SpringBootTest(classes = SpringBootTestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) class MyApplicationTests { } ===== @TestProperties ===== * [[https://www.baeldung.com/spring-test-property-source|A Quick Guide to @TestPropertySource | Baeldung]] * 테스트용 프라퍼티 오버라이드 @TestPropertySource(locations="classpath:test.properties") public class ExampleApplicationTests { } You can use @TestPropertySource @TestPropertySource( properties = { "some.username=validate", "some.password=false" } ) ===== @WebFluxTest ===== * ''@WebFluxTest'' 시에 [[java:jackson|Java Jackson JSON Library]] ''ObjectMapper'' 제대로 생성 못하는 문제 발생. 2.0.7에서 해결됨. * [[https://stackoverflow.com/questions/53208701/webfluxtest-does-not-create-objectmapper-when-upgraded-to-spring-boot-2-1-0-rel|@WebFluxTest does not create ObjectMapper when upgraded to Spring Boot 2.1.0.RELEASE - Stack Overflow]] * [[https://github.com/spring-projects/spring-boot/issues/15070|When using WebFluxTest, WebTestClient's codecs are not customized breaking JSON (de)serialisation that relies on Module-provided functionality · Issue #15070 · spring-projects/spring-boot]] * [[java:spock|Spock]]에서 호출시 ''uri(...)'' 를 호출하고 나면 Generic Type을 놓치는 현상 발생([[:intellij_idea|IntelliJ IDEA]] 버그일 수 있음). 무시하고 계속 개발. * [[http://www.mkyong.com/spring-boot/spring-webflux-test-timeout-on-blocking-read-for-5000-milliseconds/|Spring WebFlux Test – Timeout on blocking read for 5000 MILLISECONDS – Mkyong.com]] ===== 참조 ===== * [[http://www.baeldung.com/spring-boot-testing|Testing in Spring Boot | Baeldung]] * [[http://meetup.toast.com/posts/124|Spring Boot Test : TOAST Meetup]] * [[http://hyper-cube.io/2017/08/06/spring-boot-test-1/|Spring Boot에서 테스트를 - 1]] * [[http://hyper-cube.io/2017/08/10/spring-boot-test-2/|Spring Boot에서 테스트를 - 2]] * [[https://allegro.tech/2018/04/Spring-WebMvcTest-with-Spock.html|Spring @WebMvcTest with Spock Framework · allegro.tech]] * [[https://objectpartners.com/2018/06/14/spock-1-2-annotations-for-spring-integration-testing/|Spock 1.2 and Spring Integration Testing | Object Partners]] * [[https://solidsoft.wordpress.com/2018/09/03/spock-1-2-hassle-free-spring-beans-mocking-in-integration-tests/|Spock 1.2 – hassle-free Spring beans mocking in integration tests | Solid Soft]] * [[https://content.pivotal.io/springone-platform-2017/test-driven-development-with-spring-boot-sannidhi-jalukar-madhura-bhave|Test Driven Development with Spring Boot - Sannidhi Jalukar, Madhura Bhave]] * [[https://grokonez.com/testing/springboot-webflux-test-webfluxtest|SpringBoot WebFlux Test - @WebFluxTest - grokonez]] * [[http://www.mkyong.com/spring-boot/spring-boot-junit-5-mockito/|Spring Boot + JUnit 5 + Mockito – Mkyong.com]] * [[https://goddaehee.tistory.com/210?category=367461|갓대희의 작은공간 :: [스프링부트 (8)] SpringBoot Test(1) - Junit 설정 및 실행]] * [[https://goddaehee.tistory.com/211?category=367461|갓대희의 작은공간 :: [스프링부트 (9)] SpringBoot Test(2) - @SpringBootTest로 통합테스트 하기]] * [[https://goddaehee.tistory.com/212?category=367461|갓대희의 작은공간 :: [스프링부트 (10)] SpringBoot Test(3) - 단위 테스트(@WebMvcTest, @DataJpaTest, @RestClientTest 등)]] * [[http://wonwoo.ml/index.php/post/1926|Spring Boot test annotation - 머루의개발블로그]] * [[https://huisam.tistory.com/entry/springBootTest|Spring Boot Context Test - 스프링 컨텍스트 테스트 (aka. IntegrationTest) — 천천히 올바르게]] * [[https://reflectoring.io/spring-boot-test/|Testing with Spring Boot and @SpringBootTest]]