我有一个 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
线程将 fork 调用 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.
}
关于java - JUnit 测试 Spring @Async void 服务方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42438862/