如何编写 PowerMock 测试用例?

How to write PowerMock test case?

我想测试以下方法。由于 Paths 是最终的 class 我使用了 powermock。

@Service
public class MyLoader {
  public String load(String p) throws IOException {
    Path aPath = Paths.get(p);
    return IOUtils.toString(spreadsheetFilePath.toUri(), StandardCharsets.UTF_8);
  }
}

我的测试用例:

@RunWith(PowerMockRunner.class)
public class MyTest {

  MyLoader myLoader = new MyLoader();

  @Test
  public void loadTest() throws IOException {
    Paths mockPaths = PowerMockito.mock(Paths.class);
    URI   mockURI   = PowerMockito.mock(URI.class);

    Path    path     = mock(Path.class);
    IOUtils ioUtils  = mock(IOUtils.class);

    when(path.toUri()).thenReturn(mockURI);
    when(mockPaths.get(anyString())).thenReturn(path); // Error here with anyString()
    when(ioUtils.toString(mockURI, anyString())).thenReturn("test");

    String testPathStr = myLoader.load("test");
    assertThat(testPathStr, is("test"));
  }
}

我遇到异常:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Misplaced or misused argument matcher detected here:

-> at com.MyTest.loadTest(MyLoader.java:20)

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"))

This message may appear after an NullPointerException if the last matcher is returning an object 
like any() but the stubbed method signature expect a primitive argument, in this case,
use primitive alternatives.
    when(mock.get(any())); // bad use, will raise NPE
    when(mock.get(anyInt())); // correct usage use

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.

我尝试了很多不同的方法,但得到了不同类型的异常。对于这种简单的方法,我想知道编写 mockito 测试用例的最佳方法是什么。

您需要设置静态调用

@RunWith(PowerMockRunner.class)
@PrepareForTest(Paths.class, IOUtils.class) // The static classes that will be called.
public class MyTest {
    @Test
    public void loadTest() throws IOException {
        //Arrange
        // mock all the static methods in a class called "Paths"
        PowerMockito.mockStatic(Paths.class);
        // mock all the static methods in a class called "IOUtils"
        PowerMockito.mockStatic(IOUtils.class);

        // use Mockito to set up your expectation
        String expected = "test";
        Path path = mock(Path.class);
        when(Paths.get(anyString())).thenReturn(path);
        when(IOUtils.toString(any(URI.class), anyString())).thenReturn(expected);

        MyLoader myLoader = new MyLoader();

        //Act
        String actual = myLoader.load("anything");

        //Assert
        assertThat(actual, is(expected));
    }
}

引用Using PowerMock with Mockito: Mocking Static Method