Abd*_*ull 22 java junit spring spring-async
我有一个Spring服务:
@Service
@Transactional
public class SomeService {
@Async
public void asyncMethod(Foo foo) {
// processing takes significant time
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个集成测试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.
}
Run Code Online (Sandbox Code Playgroud)
这是问题所在:
SomeService.asyncMethod(..)
与注释@Async
和SpringJUnit4ClassRunner
坚持@Async
语义该testAsyncMethod
线程将呼叫分叉someService.asyncMethod(testData)
到自己的工作线程,然后直接继续执行verifyResults()
,以前的工作线程完成其工作可能之前.
someService.asyncMethod(testData)
在验证结果之前,我该如何等待完成?请注意,如何使用Spring 4和注释编写单元测试来验证异步行为?不要在这里申请,作为someService.asyncMethod(testData)
回报void
,而不是Future<?>
.
Abd*_*ull 21
对于@Async
要遵守的语义,一些活动@Configuration
类将具有@EnableAsync
注释,例如
@Configuration
@EnableAsync
@EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {
//
}
Run Code Online (Sandbox Code Playgroud)
为解决我的问题,我介绍了一个新的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
}
Run Code Online (Sandbox Code Playgroud)
如果非异步轮廓是活动的,则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
}
Run Code Online (Sandbox Code Playgroud)
现在在有问题的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.
}
Run Code Online (Sandbox Code Playgroud)
bas*_*iat 12
我已经通过注入 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();
}
Run Code Online (Sandbox Code Playgroud)
如果您使用的是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();
Run Code Online (Sandbox Code Playgroud)
您也可以使用Awaitility(在Internet上找到它,还没有尝试过)。 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) );
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
16117 次 |
最近记录: |