[SPRING] JUnit- Spring @Async void 서비스 메소드 테스트
SPRINGJUnit- Spring @Async void 서비스 메소드 테스트
나는 스프링 서비스를 가지고있다 :
@Service
@Transactional
public class SomeService {
@Async
public void asyncMethod(Foo foo) {
// processing takes significant time
}
}
그리고이 SomeService에 대한 통합 테스트가 있습니다.
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest
@Transactional
public class SomeServiceIntTest {
@Inject
private SomeService someService;
@Test
public void testAsyncMethod() {
Foo testData = prepareTestData();
someService.asyncMethod(testData);
verifyResults();
}
// verifyResult() with assertions, etc.
}
문제는 다음과 같습니다.
testAsyncMethod 스레드는 someService.asyncMethod (testData) 호출을 자체 작업자 스레드로 분기 한 다음 이전 작업자 스레드가 작업을 완료하기 전에 직접 verifyResults ()를 계속 실행합니다.
어떻게 결과를 확인하기 전에 someService.asyncMethod (testData)의 완료를 기다릴 수 있습니까? Spring 4 및 주석을 사용하여 비동기 동작을 확인하기위한 유닛 테스트를 작성하려면 어떻게해야합니까? someService.asyncMethod (testData)가 Future >가 아닌 void를 반환하기 때문에 여기에 적용하지 마십시오.
해결법
-
==============================
1.@Async 의미를 준수하기 위해 일부 활성 @Configuration 클래스에는 @EnableAsync 주석이 있습니다 (예 :
@Async 의미를 준수하기 위해 일부 활성 @Configuration 클래스에는 @EnableAsync 주석이 있습니다 (예 :
@Configuration @EnableAsync @EnableScheduling public class AsyncConfiguration implements AsyncConfigurer { // }
문제점을 해결하기 위해 비동기가 아닌 새로운 Spring 프로파일을 소개했습니다.
비동기 프로파일이 활성화되어 있지 않으면 AsyncConfiguration이 사용됩니다.
@Configuration @EnableAsync @EnableScheduling @Profile("!non-async") public class AsyncConfiguration implements AsyncConfigurer { // this configuration will be active as long as profile "non-async" is not (!) active }
비동기 프로필이 활성화되어 있으면 NonAsyncConfiguration이 사용됩니다.
@Configuration // notice the missing @EnableAsync annotation @EnableScheduling @Profile("non-async") public class NonAsyncConfiguration { // this configuration will be active as long as profile "non-async" is active }
이제 문제가되는 JUnit 테스트 클래스에서 비동기 동작을 상호 배제하기 위해 "비동기"프로파일을 명시 적으로 활성화합니다.
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration @IntegrationTest @Transactional @ActiveProfiles(profiles = "non-async") public class SomeServiceIntTest { @Inject private SomeService someService; @Test public void testAsyncMethod() { Foo testData = prepareTestData(); someService.asyncMethod(testData); verifyResults(); } // verifyResult() with assertions, etc. }
-
==============================
2.Mockito (직접 또는 Spring 테스트 지원 @MockBean을 통해)를 사용하는 경우,이 경우에 대해 시간 초과가있는 확인 모드가 있습니다. https://static.javadoc.io/org.mockito/mockito-core/2.10.0/org/mockito/Mockito.html#22
Mockito (직접 또는 Spring 테스트 지원 @MockBean을 통해)를 사용하는 경우,이 경우에 대해 시간 초과가있는 확인 모드가 있습니다. https://static.javadoc.io/org.mockito/mockito-core/2.10.0/org/mockito/Mockito.html#22
someAsyncCall(); verify(mock, timeout(100)).someMethod();
당신은 또한 Awaitility를 사용할 수 있습니다 (인터넷에서 찾았고 시도하지 않았습니다). https://blog.jayway.com/2014/04/23/java-8-and-assertj-support-in-awaitility-1-6-0/
someAsyncCall(); await().until( () -> assertThat(userRepo.size()).isEqualTo(1) );
-
==============================
3.메소드가 CompletableFuture를 리턴 할 경우 Join 메소드 - documentation CompletableFuture :: join을 사용하십시오.
메소드가 CompletableFuture를 리턴 할 경우 Join 메소드 - documentation CompletableFuture :: join을 사용하십시오.
이 메서드는 비동기 메서드가 완료 될 때까지 기다렸다가 결과를 반환합니다. 발생한 모든 예외는 주 스레드에서 다시 발생합니다.
from https://stackoverflow.com/questions/42438862/junit-testing-a-spring-async-void-service-method by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring Framework - GET과 POST의 차이점 (0) | 2019.07.11 |
---|---|
[SPRING] Spring Data JPA - 프로그래밍 방식으로 JpaRepository 기본 패키지를 설정하는 방법 (0) | 2019.07.11 |
[SPRING] 스프링 보안의 여러 antmatchers (0) | 2019.07.10 |
[SPRING] Spring : POST body에서 매개 변수를 얻는 방법? (0) | 2019.07.10 |
[SPRING] @SpringBootConfiguration과 @Configuration의 차이점은 무엇입니까? (0) | 2019.07.10 |