PowerMock's expectNew() isn't mocking a constructor as expected

AdamSpurgin picture AdamSpurgin · Sep 11, 2012 · Viewed 20.7k times · Source

I'm trying to learn the ins and outs of various mocking libraries and PowerMock(specifically the EasyMock extension) is next on the list. I'm attempting to mock a constructor and the examples provided don't have the same response when I try to replicate them. As far as I can tell, it never mocks the constructor and just proceeds as if it were normal.

This is the test class:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Writer.class})
public class FaultInjectionSituationTest {

    @Test
    public void testActionFail() throws Exception {
        FaultInjectionSituation fis = new FaultInjectionSituation();
        PowerMock.expectNew(Writer.class, "test")
           .andThrow(new IOException("thrown from mock"));
        PowerMock.replay(Writer.class);
        System.out.println(fis.action());
        PowerMock.verify(Writer.class);
    }

}

I've tried replacing the "test" with an EasyMock.isA(String.class), but it yielded the same results.

This is the FaultInjectionSituation:

public class FaultInjectionSituation {

    public String action(){
        Writer w;
        try {
            w = new Writer("test");
        } catch (IOException e) {
            System.out.println("thrown: " + e.getMessage());
            return e.getLocalizedMessage();
        }
        return "returned without throw";
    }
}

The "Writer" is nothing more than a shell of a class:

public class Writer {
    public Writer(String s) throws IOException {
    }

    public Writer() throws IOException{
    }
}

When the test is run, it prints out "returned without throw", indicating the exception was never thrown.

Answer

rrufai picture rrufai · Sep 11, 2012

You need to prepare the class that is calling the constructor as well, so PowerMock knows to expect a mocked constructor call. Try updating your code with the following:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Writer.class, FaultInjectionSituation.class})
public class FaultInjectionSituationTest { 
 // as before
}