Friday, 11 November 2016

Mocking Static Classes with Powermock

I always forget how to do this and have to look it up every time so here is a quick example for future reference!

- Annotate the class with @RunWith(PowerMockRunner.class)
- Annotate the class with @PrepareForTest(<class-to-mock>.class)
- Mock the static in @Before or in @Test PowerMockito.mockStatic(<class-to-mock>.class)
- Set expectations with when(<class-to-mock.class>.something()).thenReturn(something_else)

Example

This is a simple example which mocks StringUtils (apache commons-lang3).  This shows that the StringUtils.isBlank() method can be mocked to return different values.

    import static org.junit.Assert.assertFalse;
    import static org.junit.Assert.assertTrue;
    import static org.mockito.Mockito.when;

    import org.apache.commons.lang3.StringUtils;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;

    /**
     * An example of using powermock to mock a static class.
     */
    @RunWith(PowerMockRunner.class)
    @PrepareForTest(StringUtils.class)
    public class ExampleTest {

        /**
         * Test blank when mocked to return that an empty string isn't blank!
         */
        @Test
        public void testBlankMocked()
        {
            // Arrange
            PowerMockito.mockStatic(StringUtils.class);
            when(StringUtils.isBlank("")).thenReturn(false);
        
            // Act
            final boolean blank = StringUtils.isBlank("");

            // Assert
            assertFalse(blank);
        }
    
        /**
         * Test blank using the standard non-mocked behaviour.
         */
        @Test
        public void testBlankNormal()
        {
            // Act
            final boolean blank = StringUtils.isBlank("");

            // Assert
            assertTrue(blank);
        }
    }


Maven Dependencies

The powermock dependencies used for this test are,

    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>1.6.5</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito</artifactId>
        <version>1.6.5</version>
        <scope>test</scope>
    </dependency>