JUnit使用Mockito测试异步方法 [英] JUnit testing an asynchronous method with Mockito
问题描述
我已经使用Spring Framework(版本5.0.5.RELEASE)在Java 1.8类中实现了异步方法:
I have implemented an asynchronous method in a Java 1.8 class using Spring Framework (version 5.0.5.RELEASE):
public class ClassToBeTested {
@Autowired
private MyComponent myComponent;
@Async
public void doStuff(List<MyClass> myObjects) {
CompletableFuture<MyResponseObject>[] futureList = new CompletableFuture[myObjects.size()];
int count = 0;
for (MyClass myObject : myObjects) {
futureList[count] = myComponent.doOtherStuff(myObject);
count++;
}
// Wait until all doOtherStuff() calls have been completed
CompletableFuture.allOf(futureList).join();
... other stuff ...
}
}
我正在尝试使用JUnit和Mockito测试该类.我将其设置如下,目的是模拟doStuff()方法对组件的调用:
I'm trying to test the class with JUnit and Mockito. I have set it up as follows, with an aim of mocking the doStuff() method's call to the component:
@MockBean
private MyComponent myComponentAsAMock;
@InjectMocks
@Autowired
private ClassToBeTested classToBeTested;
@Test
public void myTest() throws Exception {
// Create object to return when myComponent.doOtherStuff() is called.
CompletableFuture<MyResponseObject> completableFuture = new CompletableFuture<MyResponseObject>();
... populate an instance of MyResponseObject ...
completableFuture.complete(myResponseObject);
// Return object when myComponent.doOtherStuff() is called.
Mockito.when(
myComponentAsAMock.doOtherStuff(ArgumentMatchers.any(MyClass.class)))
.thenReturn(completableFuture);
// Test.
List<MyClass> myObjects = new ArrayList<MyClass>();
MyClass myObject = new MyClass();
myobjects.add(myObject);
classToBeTested.doStuff(myObjects);
}
虽然我在Eclipse中单独运行该单元测试似乎成功,但是在整个项目的Maven构建中,我注意到正在抛出NullPointerExceptions:
Whilst the unit test seems to be successful when I run it individually in Eclipse, but doing a Maven build of the whole project I notice NullPointerExceptions are being thrown:
[ThreadExecutor2] .a.i.SimpleAsyncUncaughtExceptionHandler : Unexpected error occurred invoking async method 'public void package.ClassToBeTested.doStuff(java.util.List)'.
java.lang.NullPointerException: null
at java.util.concurrent.CompletableFuture.andTree(CompletableFuture.java:1306) ~[na:1.8.0_131]
at java.util.concurrent.CompletableFuture.allOf(CompletableFuture.java:2225) ~[na:1.8.0_131]
at package.ClassToBeTested.doStuff(ClassToBeTested.java:75) ~[classes/:na]
在ClassToBeTested.java的这一行上将引发错误:
The error is being raised on this line of ClassToBeTested.java:
CompletableFuture.allOf(completedFutureList).join();
看起来 就像测试完成后Maven构建输出中显示异常消息(还有其他正在运行的测试,其输出发生在显示错误消息之前),所以我我猜这与doStuff()的调用是异步的有关.
It looks like the exception message is being displayed in the Maven build output after the test has finished (there are other tests being run whose output occur before the error message is being displayed), so I'm guessing it's something to do with the fact that the call to doStuff() is asynchronous.
任何帮助将不胜感激.
推荐答案
解决方案是在Mockito验证步骤中添加超时和检查,以确保模拟的组件的方法已被调用了适当的次数:
The solution was to add in a Mockito verification step with a timeout and a check to ensure that the mocked component's method had been called the appropriate number of times:
Mockito.verify(myComponentAsAMock, Mockito.timeout(1000).times(1)).doOtherStuff(ArgumentMatchers.any(MyClass.class));
这篇关于JUnit使用Mockito测试异步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!