JUnit使用Mockito测试异步方法 [英] JUnit testing an asynchronous method with Mockito

查看:207
本文介绍了JUnit使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆