2017-02-24 15 views
6

bir bahar @Async boşluk hizmeti yöntemi JUnit-test:Bir Bahar hizmeti

@Service 
@Transactional 
public class SomeService { 

    @Async 
    public void asyncMethod(Foo foo) { 
     // processing takes significant time 
    } 
} 

Ve bu SomeService için bir entegrasyon test var: Burada

@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. 
} 

sorundur:

SomeService.asyncMethod(..) olarak
  • @Async ve
  • ile açıklamalı SpringJUnit4ClassRunner olarak
  • testAsyncMethod iplik daha sonra doğrudan önceki çalışan iş parçacığı çalışmalarını tamamladığında muhtemelen önce verifyResults() yürütme devam kendi işçi iş parçacığı içine çağrı someService.asyncMethod(testData) çatal olacak

@Async semantik uyar.

nasıl sonuçlarının doğrulanması önce someService.asyncMethod(testData) 'ın tamamlanması için bekleyebilir? How do I write a unit test to verify async behavior using Spring 4 and annotations? çözümleri someService.asyncMethod(testData) getiri void değil, bir Future<?> olarak, burada geçerli değildir dikkat edin.

cevap

8

@Async semantik yapıştırılacak için, some active @Configuration class will have the @EnableAsync annotation, ör Benim sorunu çözmek için

@Configuration 
@EnableAsync 
@EnableScheduling 
public class AsyncConfiguration implements AsyncConfigurer { 

    // 

} 

, ben yeni bahar profili non-async tanıtıldı. non-async profil değil aktifse

, AsyncConfiguration kullanılır:

@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 

} 

zaman uyumsuz olmayan profili aktif ise, NonAsyncConfiguration kullanılır: Şimdi

@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 

} 

Sorunlu JUnit test sınıfında, eşzamansız davranışı karşılıklı olarak dışlamak için "eşzamansız" profili açıkça etkinleştirdim:

@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. 
} 
1

Eğer Mockito (doğrudan veya Yay kontrol desteği @MockBean üzerinden) kullanıyorsanız, tam olarak bu durum için zaman aşımı ile bir doğrulama moduna sahiptir: https://static.javadoc.io/org.mockito/mockito-core/2.10.0/org/mockito/Mockito.html#22

someAsyncCall(); 
verify(mock, timeout(100)).someMethod(); 

Ayrıca Awaitility (kullanabilirsiniz İnternette buldum, denemedim). documentation CompletableFuture::join - 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)); 
0

durumda sizin yöntem CompletableFuture kullanacağım join yöntemi döndürür.

Bu yöntem, async yönteminin sonucunu bitirip sonucunu döndürmesini bekler. Karşılık gelen herhangi bir istisna ana iş parçacığında yeniden işlenir.