我有一个 Spring 服务:

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

这是问题所在:
  • 作为SomeService.asyncMethod(..)@Async
  • 注释
  • ,因为SpringJUnit4ClassRunner遵循@Async语义
  • testAsyncMethod线程会将调用someService.asyncMethod(testData)派生到其自己的工作线程中,然后直接继续执行verifyResults(),可能在上一个工作线程完成工作之前。

    如何在验证结果之前等待someService.asyncMethod(testData)的完成?请注意,How do I write a unit test to verify async behavior using Spring 4 and annotations?的解决方案在这里不适用,因为someService.asyncMethod(testData)返回void,而不是Future<?>

    最佳答案

    为了遵守@Async语义,some active @Configuration class will have the @EnableAsync annotation例如

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

    为了解决我的问题,我引入了一个新的Spring配置文件non-async

    如果non-async配置文件是而不是处于 Activity 状态,则使用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
    
    }
    

    如果非异步配置文件处于 Activity 状态,则使用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.
    }
    

    10-07 18:54
    查看更多