Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 使用Mockito对调用异步函数的函数进行单元测试_Unit Testing_Junit_Mockito - Fatal编程技术网

Unit testing 使用Mockito对调用异步函数的函数进行单元测试

Unit testing 使用Mockito对调用异步函数的函数进行单元测试,unit-testing,junit,mockito,Unit Testing,Junit,Mockito,我有一个调用异步函数的方法: public class MyService { ... public void uploadData() { MyPool.getInstance().getThreadPool().execute(new Runnable() { @Override public void run() { boolean suc = upload();

我有一个调用异步函数的方法:

public class MyService {
  ...
  public void uploadData() {
    MyPool.getInstance().getThreadPool().execute(new Runnable() {
                @Override
                public void run() {
                    boolean suc = upload();
                }
            });
        }
}
我想用以下方法对该函数进行单元测试:

MyPool mockMyPool = Mockito.mock(MyPool.class);
ThreadPool mockThreadPool = Mockito.mock(ThreadPool.class);
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);

when(mockMyPool.getThreadPool()).thenReturn(mockThreadPool);
MyService service = new MyService();

// run the method under test
service.uploadData();

// set the runnableCaptor to hold your callback
verify(mockThreadPool).execute(runnableCaptor.capture());
MyPool mockMyPool=Mockito.mock(MyPool.class);
ThreadPool mockThreadPool=Mockito.mock(ThreadPool.class);
ArgumentCaptor runnableCaptor=ArgumentCaptor.forClass(Runnable.class);
当(mockMyPool.getThreadPool())。然后返回(mockThreadPool);
MyService service=newmyservice();
//运行测试中的方法
service.uploadData();
//设置runnableCaptor以保持回调
验证(mockThreadPool).execute(runnableCaptor.capture());
但我有一个错误:

org.mockito.exceptions.verification.WantedButNotInvoked: 
Wanted but not invoked:
threadPool.execute(
    <Capturing argument>
);
org.mockito.exceptions.verification.wantedbutnotcalled:
需要但未调用:
threadPool.execute(
);

为什么会出现这个错误,如何用Mockito对uploadData()函数进行单元测试?

好的,我自己想出了一个方法,因为
MyPool
是一个单例。我添加了一个公共函数
setInstance(mockedInstance)
来将模拟的实例传递给
MyPool
。然后,它起作用了。我知道这有点“脏”,但如果你有更好的解决方案,请让我知道。谢谢

除了您发现的保留MyPool或ThreadPool字段的DI方法外,您还可以稍微进行重构,以允许在方法中注入依赖项:

这可能更干净,因为它将您的线程池降低到您需要的抽象级别(Executor),这意味着您只模拟了一个方法接口,而不是线程池(我假设它与ThreadPoolService相关;否则,您也可以接受线程池)。您的
uploadData()
将不会经过正式测试,但您可以轻松彻底地测试
uploadData(Executor)
uploadData(ThreadPool)
,它们是最有可能断裂的运动部件


包私有技巧依赖于代码和测试在同一个包中,尽管它们可能在不同的源文件夹中;或者,您可以将ThreadPool接收调用作为公共API的一部分,这将允许以后更加灵活。

MyPool.getInstance()如何知道您的
mockMyPool
并将其返回?使用而不是单例。
public class MyService {
  ...
  public void uploadData() {
    uploadData(MyPool.getInstance().getThreadPool());
  }

  /** Receives an Executor for execution. Package-private for testing. */
  void uploadData(Executor executor) {
    executor.execute(new Runnable() {
      @Override public void run() {
        boolean suc = upload();
      }
    });
  }
}