Search code examples
mockitopowermockpowermockito

How to write PowerMock test case?


I want to test the following method. As Paths is a final class I used 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);
  }
}

My Test Case:

@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"));
  }
}

I get exception:

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.

I have tried many different ways but getting different types of exception. I want to know for such a simple method what's the best way to write mockito test case.


Solution

  • You would need to setup the static calls

    @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));
        }
    }
    

    Reference Using PowerMock with Mockito: Mocking Static Method