1. 개요
이 예제에서는 Spring Boot 통합 테스트 중에 ApplicationRunner 또는 CommandLineRunner 유형의 Bean이 실행 되지 않도록 방지하는 방법을 보여줍니다 .
2. 예제 애플리케이션
예제 애플리케이션은 명령 줄 실행기, 애플리케이션 실행기 및 태스크 서비스 빈으로 구성됩니다.
명령 줄 실행기 는 응용 프로그램 시작시 작업을 수행하기 위해 작업 서비스의 실행 메서드를 호출합니다 .
@Component
public class CommandLineTaskExecutor implements CommandLineRunner {
private TaskService taskService;
public CommandLineTaskExecutor(TaskService taskService) {
this.taskService = taskService;
}
@Override
public void run(String... args) throws Exception {
taskService.execute("command line runner task");
}
}
같은 방식으로 애플리케이션 실행기는 작업 서비스와 상호 작용하여 다른 작업을 수행합니다.
@Component
public class ApplicationRunnerTaskExecutor implements ApplicationRunner {
private TaskService taskService;
public ApplicationRunnerTaskExecutor(TaskService taskService) {
this.taskService = taskService;
}
@Override
public void run(ApplicationArguments args) throws Exception {
taskService.execute("application runner task");
}
}
마지막으로 작업 서비스는 클라이언트의 작업을 실행합니다.
@Service
public class TaskService {
private static Logger logger = LoggerFactory.getLogger(TaskService.class);
public void execute(String task) {
logger.info("do " + task);
}
}
그리고 모든 것이 작동하도록하는 Spring Boot 애플리케이션 클래스도 있습니다.
@SpringBootApplication
public class ApplicationCommandLineRunnerApp {
public static void main(String[] args) {
SpringApplication.run(ApplicationCommandLineRunnerApp.class, args);
}
}
3. 예상되는 동작 테스트
ApplicationRunnerTaskExecutor 과 CommandLineTaskExecutor의 Spring 부팅로드 응용 프로그램 컨텍스트 후 실행됩니다.
간단한 테스트를 통해이를 확인할 수 있습니다.
@SpringBootTest
class RunApplicationIntegrationTest {
@SpyBean
ApplicationRunnerTaskExecutor applicationRunnerTaskExecutor;
@SpyBean
CommandLineTaskExecutor commandLineTaskExecutor;
@Test
void whenContextLoads_thenRunnersRun() throws Exception {
verify(applicationRunnerTaskExecutor, times(1)).run(any());
verify(commandLineTaskExecutor, times(1)).run(any());
}
}
보시다시피, 우리는 Mockito 스파이 를 ApplicationRunnerTaskExecutor 및 CommandLineTaskExecutor 빈 에 적용하기 위해 SpyBean 어노테이션을 사용하고 있습니다. 그렇게함으로써 이러한 각 빈 의 실행 메소드가 한 번 호출 되었는지 확인할 수 있습니다 .
다음 섹션에서는 Spring Boot 통합 테스트 중에 이러한 기본 동작을 방지하는 다양한 방법과 기술을 살펴 보겠습니다.
4. 스프링 프로파일을 통한 예방
이 두 가지가 실행되는 것을 막을 수있는 한 가지 방법은 @Profile 로 어노테이션을 달아주는 것입니다 .
@Profile("!test")
@Component
public class CommandLineTaskExecutor implements CommandLineRunner {
// same as before
}
@Profile("!test")
@Component
public class ApplicationRunnerTaskExecutor implements ApplicationRunner {
// same as before
}
위의 변경 후 통합 테스트를 진행합니다.
@ActiveProfiles("test")
@SpringBootTest
class RunApplicationWithTestProfileIntegrationTest {
@Autowired
private ApplicationContext context;
@Test
void whenContextLoads_thenRunnersAreNotLoaded() {
assertNotNull(context.getBean(TaskService.class));
assertThrows(NoSuchBeanDefinitionException.class,
() -> context.getBean(CommandLineTaskExecutor.class),
"CommandLineRunner should not be loaded during this integration test");
assertThrows(NoSuchBeanDefinitionException.class,
() -> context.getBean(ApplicationRunnerTaskExecutor.class),
"ApplicationRunner should not be loaded during this integration test");
}
}
보시다시피 위의 테스트 클래스에 @ActiveProfiles ( "test") 어노테이션을 추가했습니다. 이는 @Profile ( "! test") 어노테이션이 달린 항목을 연결하지 않음을 의미합니다 . 결과적으로 CommandLineTaskExecutor Bean과 ApplicationRunnerTaskExecutor Bean이 전혀로드 되지 않습니다 .
5. ConditionalOnProperty 어노테이션을 통한 예방
또는 속성별로 연결을 구성한 다음 ConditionalOnProperty 어노테이션 을 사용할 수 있습니다 .
@ConditionalOnProperty(
prefix = "application.runner",
value = "enabled",
havingValue = "true",
matchIfMissing = true)
@Component
public class ApplicationRunnerTaskExecutor implements ApplicationRunner {
// same as before
}
@ConditionalOnProperty(
prefix = "command.line.runner",
value = "enabled",
havingValue = "true",
matchIfMissing = true)
@Component
public class CommandLineTaskExecutor implements CommandLineRunner {
// same as before
}
우리가 볼 때, ApplicationRunnerTaskExecutor 과 CommandLineTaskExecutor은 기본적으로 활성화되어, 우리가 다음과 같은 속성을 설정하면 우리는 그들을 해제 할 수 있습니다 거짓을 :
- command.line.runner.enabled
- application.runner.enabled
따라서 테스트에서 이러한 속성을 false로 설정 하고 ApplicationRunnerTaskExecutor 또는 CommandLineTaskExecutor Bean이 애플리케이션 컨텍스트에로드 되지 않습니다 .
@SpringBootTest(properties = {
"command.line.runner.enabled=false",
"application.runner.enabled=false" })
class RunApplicationWithTestPropertiesIntegrationTest {
// same as before
}
이제 위의 기술이 목표를 달성하는 데 도움이되지만 모든 Spring Bean이 올바르게로드되고 연결되었는지 테스트하려는 경우가 있습니다.
예를 들어, TaskService 빈이 CommandLineTaskExecutor에 올바르게 주입되었는지 테스트하고 싶을 수 있지만 여전히 테스트 중에 실행 메서드가 실행되는 것을 원하지 않습니다 . 그래서 우리가 그것을 달성 할 수있는 방법을 설명하는 마지막 섹션을 봅시다.
6. 전체 컨테이너를 부트 스트랩하지 않음으로써 예방
여기에서는 전체 애플리케이션 컨테이너를 부트 스트랩하지 않음 으로써 CommandLineTaskExecutor 및 ApplicationRunnerTaskExecutor Bean이 실행 되지 않도록 방지 할 수있는 방법을 설명합니다 .
이전 섹션에서는 @SpringBootTest 어노테이션 을 사용했으며 이로 인해 통합 테스트 중에 전체 컨테이너가 부트 스트랩되었습니다. @SpringBootTest 에는 이 마지막 솔루션과 관련된 두 개의 메타 어노테이션 이 포함되어 있습니다.
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
글쎄, 테스트 중에 전체 컨테이너를 부트 스트랩 할 필요가 없다면 @BootstrapWith 를 사용하고 싶지 않습니다 .
대신 @ContextConfiguration으로 바꿀 수 있습니다 .
@ContextConfiguration(classes = {ApplicationCommandLineRunnerApp.class},
initializers = ConfigDataApplicationContextInitializer.class)
@ContextConfiguration을 사용 하여 통합 테스트를 위해 애플리케이션 컨텍스트를로드하고 구성하는 방법을 결정합니다. ContextConfiguration 클래스 속성 을 설정하여 Spring Boot가 ApplicationCommandLineRunnerApp 클래스를 사용하여 애플리케이션 컨텍스트를로드하도록 선언합니다 . 이니셜 라이저를 ConfigDataApplicationContextInitializer 로 정의하여 응용 프로그램은 해당 속성을로드합니다 .
Spring TestContext Framework를 JUnit 5의 Jupiter 프로그래밍 모델에 통합하기 때문에 여전히 @ExtendWith (SpringExtension.class) 가 필요합니다 .
위의 결과로 Spring Boot 애플리케이션 컨텍스트는 CommandLineTaskExecutor 또는 ApplicationRunnerTaskExecutor Bean 을 실행하지 않고 애플리케이션의 구성 요소 및 속성을로드합니다 .
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { ApplicationCommandLineRunnerApp.class },
initializers = ConfigDataApplicationContextInitializer.class)
public class LoadSpringContextIntegrationTest {
@SpyBean
TaskService taskService;
@SpyBean
CommandLineRunner commandLineRunner;
@SpyBean
ApplicationRunner applicationRunner;
@Test
void whenContextLoads_thenRunnersDoNotRun() throws Exception {
assertNotNull(taskService);
assertNotNull(commandLineRunner);
assertNotNull(applicationRunner);
verify(taskService, times(0)).execute(any());
verify(commandLineRunner, times(0)).run(any());
verify(applicationRunner, times(0)).run(any());
}
}
또한 ConfigDataApplicationContextInitializer 가 단독으로 사용되는 경우 @Value (“$ {…}”) 삽입을 지원하지 않는다는 점을 명심해야 합니다 . 이를 지원하려면 PropertySourcesPlaceholderConfigurer 를 구성해야합니다 .
7. 결론
이 기사에서는 Spring Boot 통합 테스트 중에 ApplicationRunner 및 CommandLineRunner Bean 의 실행을 방지하는 다양한 방법을 보여주었습니다 .
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/spring-junit-prevent-runner-beans-testing-execution
'Java' 카테고리의 다른 글
RestTemplate을 사용하여 개체 List 가져 오기 및 게시 (0) | 2021.03.22 |
---|---|
Spring RestTemplate을 통해 대용량 파일 다운로드 (0) | 2021.03.22 |
WebRTC 사용방법(예제) (1) | 2021.03.21 |
자바 컬렉션 (0) | 2021.03.21 |
Java 8의 새로운 기능 (0) | 2021.03.21 |