【发布时间】:2016-08-18 10:42:05
【问题描述】:
用 mockito 模拟异步 (@Async) 方法的最佳方法是什么?提供以下服务:
@Service
@Transactional(readOnly=true)
public class TaskService {
@Async
@Transactional(readOnly = false)
public void createTask(TaskResource taskResource, UUID linkId) {
// do some heavy task
}
}
Mockito 的验证如下:
@RunWith(SpringRunner.class)
@WebMvcTest(SomeController.class)
public class SomeControllerTest {
@Autowired
MockMvc mockMvc;
@MockBean
private TaskService taskService;
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
// other details omitted...
@Test
public void shouldVerify() {
// use mockmvc to fire to some controller which in turn call taskService.createTask
// .... details omitted
verify(taskService, times(1)) // taskService is mocked object
.createTask(any(TaskResource.class), any(UUID.class));
}
}
上面的测试方法shouldVerify总是会抛出:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
-> at SomeTest.java:77) // details omitted
-> at SomeTest.java:77) // details omitted
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
如果我从TaskService.createTask 方法中删除@Async,则不会发生上述异常。
Spring Boot 版本:1.4.0.RELEASE
Mockito 版本:1.10.19
【问题讨论】:
-
你能提供你的测试的整个实现吗?有方法 createTask 的类是超类吗?
-
嗨,Marians27,我已经编辑了这个问题。重要的一点是,如果我从 TaskService 类中删除 @Async 注释,则不会发生异常。
-
@Async注释是否会导致 aspectj 或其他东西启动?您确定您尝试验证的taskService实例没有被任何方面等修改吗? -
嗨 SpaceTrucker,将异步模式更改为 AspectJ 解决了这个问题。我仍然不知道造成这种情况的确切根本原因是什么。
标签: java spring asynchronous spring-boot mockito