在spring boot unit test中模拟Files.copy

时间:2017-03-20 07:17:51

标签: java unit-testing mockito

我试图在单元测试用例中模拟以下函数:

Files.copy(response.getBody(), pathObj, StandardCopyOption.REPLACE_EXISTING);

StandardCopyOptionjava.nio.file包的枚举:

我试图模仿的方式是:

    try {
        Mockito.doNothing().when(Files.copy(Mockito.any(InputStream.class), Mockito.any(Path.class), Mockito.any(CopyOption.class)));
    }catch (Exception e){
        e.printStackTrace();
    }

但是我收到以下错误:

    org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
0 matchers expected, 3 recorded:
-> at scheduler.DownloadTest.downloadFile(DownloadTest.java:227)
-> at scheduler.DownloadTest.downloadFile(DownloadTest.java:227)
-> at scheduler.DownloadTest.downloadFile(DownloadTest.java:227)

This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

1 个答案:

答案 0 :(得分:1)

问题在于您正在尝试模拟静态方法。 Mockito不允许这样做。您只能为实际模拟类实例的非静态方法提供行为。

使用时

Mockito.doNothing().when(Files.copy(Mockito.any(InputStream.class), Mockito.any(Path.class), Mockito.any(CopyOption.class)));

在when()方法中,mockito期望对您尝试模拟的类的引用。然后,您需要使用其参数指定方法。

例如:

Mockito.doNothing().when(classInstance).copy(...)

但是,由于此情况下的复制是静态方法,因此上述方法不起作用(在您的代码中,您提供Files.copy的返回值作为类引用)。因此,一种解决方案是使用PowerMock(可以模拟静态方法但与mockito的更高版本不兼容)或将Files类包装在实例包装器中。

例如:

class FilesWrapper {
   public long copy(InputStream in, Path target, CopyOption... options) {
      return Files.copy(in, target, options);
   }
}

现在,将模拟的FilesWrapper实例(Mockito.mock(FilesWrapper.class))注入到您的代码中,并在使用Files.copy的任何地方使用它。由于mockito的默认行为是对模拟类实例的方法不做任何操作,因此您只需要创建模拟。

另一种方法是将Files.copy部分移动到受测试类的受保护方法中。然后可以在测试期间覆盖此受保护的方法。