JUnit 测试 Spring @Async void 服务方法

新手上路,请多包涵

我有一个 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<?>

原文由 Abdull 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 654
2 个回答

对于 @Async 要遵守的语义, 一些活动的 @Configuration 类将具有 @EnableAsync 注释,例如

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

  //

}

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

如果 non-async 配置文件 激活,则使用 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.
}

原文由 Abdull 发布,翻译遵循 CC BY-SA 3.0 许可协议

我通过注入 ThreadPoolTaskExecutor 完成了

接着

executor.getThreadPoolExecutor().awaitTermination(1, TimeUnit.SECONDS);

在验证结果之前,它如下:

   @Autowired
  private ThreadPoolTaskExecutor executor;

    @Test
    public void testAsyncMethod() {

        Foo testData = prepareTestData();

        someService.asyncMethod(testData);

        executor.getThreadPoolExecutor().awaitTermination(1, TimeUnit.SECONDS);

        verifyResults();
    }

原文由 bastiat 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题