[英]How to mock Asynchronous (@Async) method in Spring Boot using Mockito?
使用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
我們希望在1.4.1中修復Spring Boot中的錯誤 。 問題是你的模擬TaskService
仍然被異步調用,這打破了Mockito。
您可以通過為TaskService
創建一個接口並創建一個模擬來解決此問題。 只要你只在實現上留下@Async
注釋就可以了。
像這樣的東西:
public interface TaskService {
void createTask(TaskResource taskResource, UUID linkId);
}
@Service
@Transactional(readOnly=true)
public class AsyncTaskService implements TaskService {
@Async
@Transactional(readOnly = false)
@Override
public void createTask(TaskResource taskResource, UUID linkId) {
// do some heavy task
}
}
發現通過將Async模式更改為AspectJ修復了問題:
@EnableCaching
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(lazyInit = true)
@EnableAsync(mode = AdviceMode.ASPECTJ) // Changes here!!!
public class Main {
public static void main(String[] args) {
new SpringApplicationBuilder().sources(Main.class)
.run(args);
}
}
在我明白這個問題的真正根源之前,我會接受這個暫時的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.