Skip to main content

Test 의 실행속도를 빠르게, Spring context mocking

· 5 min read
Haril Song
Owner, Software Engineer at 42dot

Overview

모든 프로젝트에서 테스트 코드를 작성하는 것은 이제 일상이 된지 오래다. 프로젝트가 성장해나간다면 필연적으로 테스트의 수도 많아지면서 전체 테스트 수행시간이 점점 길어지게 된다. 특히 Spring framework 을 기반으로 하는 프로젝트의 테스트를 쓰고 있다면 Spring Bean 의 Context loading 에 의해서 테스트 실행이 급격하게 느려지게 되는데, 이 글에서는 이러한 문제를 해결하기 위한 방법을 소개한다.

모든 테스트는 유닛 테스트로 작성

테스트는 빨라야 한다. 빨라야 자주 실행하는데 있어서 주저함이 없어진다. 전체 테스트 한 번 실행하는데 10분씩 걸린다면, 피드백이 10분은 지나야 온다는 의미이다.

Spring 에서의 빠른 테스트를 위해서는 @SpringBootTest 의 사용을 피해야 한다. 모든 Bean 을 불러오기 때문에 비즈니스 로직을 테스트하는 코드의 실행보다 필요한 Bean을 불러오는 시간이 압도적으로 길어진다.

@SpringBootTest
class SpringApplicationTest {

@Test
void main() {
}
}

위 코드는 Spring application 을 실행하기 위한 기본 테스트 코드다. @SpringBootTest 에 의해서 설정되어있는 모든 Bean 이 불러와진다. 어떻게 하면 필요한 Bean 만 주입받아서 테스트할 수 있을까?

Annotation or Mockito 활용

특정 어노테이션을 사용하면, 관련 테스트에 필요한 Bean 만 자동으로 불러와진다. 덕분에 모든 Bean 을 Context loading 하는 것이 아닌, 진짜 필요한 Bean 만 불러와서 테스트 수행시간을 최소화 할 수 있다.

몇가지 annotation 만 간단하게 살펴보자.

  • @WebMvcTest : Web MVC 관련 Bean 만 불러온다.
  • @WebFluxTest : Web Flux 관련 Bean 만 불러온다. WebTestClient 를 사용할 수 있다.
  • @DataJpaTest: JPA repository 관련 Bean 만 불러온다.
  • @WithMockUser: Spring Security 사용시 가짜 User 를 만들어준다. 불필요한 인증과정을 생략할 수 있다.

또한 Mockito 를 활용하면 복잡한 의존관계를 간편하게 해결하여 테스트를 작성할 수 있다. 이 두 개념을 적절히 사용한다면 대부분의 유닛 테스트는 크게 어렵지 않다.

warning

Mocking 을 너무 많이 해야한다면 의존성 설계가 잘못되었을 가능성이 높다. 남용하지 않도록 주의해야 한다.

그렇다면 SpringApplication 은?

SpringApplication 이 실행되려면 SpringApplication.run() 이 실행되어야 한다. 해당 method 의 실행을 확인하기 위해서 모든 Spring context 를 loading 하는 것은 역시 비효율적이므로, context loading 이 일어나는 SpringApplication 을 mocking 처리하고 run() 이 호출되는지만 검증하면 @SpringBootTest 를 사용하지 않고도 테스트할 수 있다.

class DemoApplicationTests {  

@Test
void main() {
try (MockedStatic<SpringApplication> springApplication = mockStatic(SpringApplication.class)) {
when(SpringApplication.run(DemoApplication.class)).thenReturn(null);

DemoApplication.main(new String[]{});

springApplication.verify(
() -> SpringApplication.run(DemoApplication.class), only()
);
}
}
}

Conclusion

로버트 마틴의 Clean Code 9장에 보면 'FIRST 원칙' 에 대해 설명하고 있다.

그 중에 첫 글자인 F, Fast(빠르게) 에 대해서 고민해본 결과를 이번 글에서 간단하게 소개해봤다. 다시 한 번 언급하며 글을 마무리한다.

테스트는 충분히 빨라야 한다. - Robert C. Martin

Reference