3

I have two line of code:

File file = new File("report_はな.html");
Path path = Paths.get(file.getCanonicalPath());

Is there anyway that I can mock the static method:

Paths.get(file.getCanonicalPath());

And only throw the exception InvalidPathException?

I tried the powermockito, but it seems does not working

PowerMockito.mockStatic(Paths.class);
PowerMockito.doReturn(null).doThrow(new InvalidPathException("","")).when(Paths.class);

The whole idea is I am trying to reproduce the bug that Under the English Mac, the Mac default encoding setting is US-ASCII, which Path path = Paths.get("report_はな.html"); will throw this InvalidPathException.

fap
  • 663
  • 1
  • 5
  • 14
XL Zheng
  • 363
  • 1
  • 6
  • 14

1 Answers1

3

As documented here, you have to jump through some hoops to mock "system" classes, i.e. classes loaded by the system classloader.

Specifically, whereas in a normal PowerMock test the @PrepareForTest() annotation identifies the class whose static methods you want to mock, in a "system" PowerMock test the annotation needs to identify the class that calls the static methods (usually the class under test).

For instance, say we have the following class:

public class Foo {
    public static Path doGet(File f) throws IOException {
        try {
            return Paths.get(f.getCanonicalPath());
        } catch (InvalidPathException e) {
            return null;
        }
    }
}

We want to test that this class does in fact return null if Paths.get() throws an InvalidPathException. To test this, we write:

@RunWith(PowerMockRunner.class)  // <- important!
@PrepareForTest(Foo.class)       // <- note: Foo.class, NOT Paths.class
public class FooTest {
    @Test
    public void doGetReturnsNullForInvalidPathException() throws IOException {
        // Enable static mocking on Paths
        PowerMockito.mockStatic(Paths.class);

        // Make Paths.get() throw IPE for all arguments
        Mockito.when(Paths.get(any(String.class)))
          .thenThrow(new InvalidPathException("", ""));

        // Assert that method invoking Paths.get() returns null
        assertThat(Foo.doGet(new File("foo"))).isNull();
    }
}

Note: I wrote Paths.get(any(String.class)) but you could mock something more specific if need be, e.g. Paths.get("foo")) or Paths.get(new File("report_はな.html").getCanonicalPath()).

David Moles
  • 48,006
  • 27
  • 136
  • 235