Search code examples
javaunit-testingmockingstatic-methodspowermock

Unable to mock System class static method using PowerMockito


Even though I have read the manual and gone through multiple answers for Powermock, could not mock a static method for my use case.

Class:

    @Component
    public class SCUtil{

        public void createSC(){
            try {
                String host = InetAddress.getLocalHost().getHostAddress();
//                ...
//                ...
//                ...
            } catch (UnknownHostException e) {
               log.error("Exception in creasting SC");
               throw new ServiceException(e);
            }
        }

    }

Test class:

@RunWith(PowerMockRunner.class)
@PrepareForTest( InetAddress.class )
public class SCUtilTest {

    @InjectMocks
    private SCUtil scUtil;

    private Event event;

    @Before
    public void beforeEveryTest () {
        event = new InterventionEvent();
    }
    
    @Test(expected = ServiceException.class)
    public void testCreateSC_Exception () {
        PowerMockito.mockStatic(InetAddress.class);
        PowerMockito.when(InetAddress.getLocalHost()).thenThrow(new UnknownHostException("test"));
        scUtil.createSC(event);
    }
}

Here, the test is failing as no exception is being thrown:

java.lang.AssertionError: Expected exception: com.example.v1.test.selftest.errorhandling.ServiceException

I have wrecked more than a couple of hours in this and still have not gotten it to work. What am I doing wrong?

Thank you for all the help in advance :)


Solution

  • java.net.InetAddress is a system class. The caller of the system class should be defined in @PrepareForTest({ClassThatCallsTheSystemClass.class}).
    See documentation.

    The way to go about mocking system classes are a bit different than usual though. Normally you would prepare the class that contains the static methods (let's call it X) you like to mock but because it's impossible for PowerMock to prepare a system class for testing so another approach has to be taken. So instead of preparing X you prepare the class that calls the static methods in X!


    Please note @InjectMocks annotation does not inject static mocks, it can be removed.

    Example of working test:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(SCUtil.class)
    public class SCUtilTest {
    
        private SCUtil scUtil = new SCUtil();
    
        @Test(expected = ServiceException.class)
        public void testCreateSC_Exception () throws UnknownHostException {
            PowerMockito.mockStatic(InetAddress.class);
            PowerMockito.when(InetAddress.getLocalHost()).thenThrow(new UnknownHostException("test"));
            scUtil.createSC();
        }
    }