4

I'm testing following private method (getPrintWriter) with reflections:

public abstract class CsvAuditor extends Auditor {

    public void run() {
        PrintWriter writer = getPrintWriter();
        if (writer == null)
            return;
        writeReport(writer);
        writer.close();
    }

    private PrintWriter getPrintWriter() {
        PrintWriter writer;
        try {
            DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd__HH_mm_ss");
            Date date = new Date();
            writer = new PrintWriter("report__" + dateFormat.format(date) + ".csv");
        }
        catch (FileNotFoundException ex) {
            System.err.println(ex.getMessage());
            return null;
        }
        return writer;
    }

}

I want to simulate that constructor of PrintWriter throwing FileNotFoundException.

@RunWith(PowerMockRunner.class)
@PrepareForTest({CsvAuditor.class, PrintWriter.class})
public class CsvAuditorTest {

    private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();

    @Before
    public void setUpStreams() {
        System.setErr(new PrintStream(errContent));
    }

    @After
    public void cleanUpStreams() {
        System.setErr(null);
    }

    @Test
    public void shouldPrintErrorIfFileIsInaccessible() throws Exception {
        //given
        Method getPrintWriter = getPrivateMethod("getPrintWriter", new Class[]{});
        CsvAuditor csvAuditor = new CsvAuditor() {
            @Override
            protected void writeReport(PrintWriter writer) {

            }
        };

        //Here is line where RuntimeException is thrown
        PowerMockito.whenNew(PrintWriter.class).withAnyArguments().thenThrow(new FileNotFoundException());


        //when
        Object result = getPrintWriter.invoke(csvAuditor);

        //then
        assertNull(result);
        assertEquals("File is inaccessible\r\n", errContent.toString());
    }

    private Method getPrivateMethod(String methodName, Class[] argTypes) throws NoSuchMethodException {
        Method method = CsvAuditor.class.getDeclaredMethod(methodName, argTypes);
        method.setAccessible(true);
        return method;
    }
}

I would like to simulate that PrintWriter constructor was thrown FileNotFoundException and then I would like to assert, that null was returned. I marked with a comment line which throw following exception and I don't know how to simulate it correctly.

> java.lang.RuntimeException: PowerMock internal error  at
> org.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing$InvokeStubMethod.invoke(DelegatingToConstructorsOngoingStubbing.java:133)
>   at
> org.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing.thenThrow(DelegatingToConstructorsOngoingStubbing.java:66)
>   at
> auditor.csv.CsvAuditorTest.shouldPrintErrorIfFileIsInaccessible(CsvAuditorTest.java:46)
>   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>   at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>   at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
>   at
> org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:312)
>   at
> org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:88)
>   at
> org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96)
>   at
> org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:296)
>   at
> org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl$PowerMockJUnit49MethodRunner.executeTestInSuper(PowerMockJUnit49RunnerDelegateImpl.java:116)
>   at
> org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl$PowerMockJUnit49MethodRunner.executeTest(PowerMockJUnit49RunnerDelegateImpl.java:77)
>   at
> org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:284)
>   at
> org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
>   at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
>   at
> org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:209)
>   at
> org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:148)
>   at
> org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
>   at
> org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
>   at
> org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
>   at
> org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
>   at
> org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
>   at
> org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
>   at
> org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
>   at org.junit.runner.JUnitCore.run(JUnitCore.java:160)   at
> com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
>   at
> com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
>   at
> com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
>   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>   at
> com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
> Caused by: java.io.FileNotFoundException  at
> org.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing$InvokeStubMethod.invoke(DelegatingToConstructorsOngoingStubbing.java:130)
>   ... 34 more
Eleid
  • 65
  • 1
  • 7

2 Answers2

10

Try below with exact argument matcher

PowerMockito.whenNew(PrintWriter.class).withArguments(Matchers.anyString()).thenThrow(new FileNotFoundException());

and I got the result object as null.

kswaughs
  • 2,967
  • 1
  • 17
  • 21
  • Wow! It works, but could you explain me why? Why my code was wrong and your code is correct? What is difference between `withArguments(Matchers.anyString())` and `withAnyArguments()` ? – Eleid Aug 17 '15 at 10:36
  • I am not sure the exact difference. Earlier in my case withAnyArguments worked with single constructor, But when multiple parameterized constructors are there it didn't work, So It is better to give exact argument matchers in such cases. – kswaughs Aug 18 '15 at 08:52
0

Here is another approach to achieve this.

whenNew(PrintWriter.class).withParameterTypes(String.class).
    withArguments(Matchers.anyString()).
    thenAnswer(new Answer<Object>() {
      @Override
      public Object answer(InvocationOnMock invocation) throws Throwable {
        throw new Exception();
      }
    });
Indra Uprade
  • 773
  • 5
  • 12