Showing posts with label Mockito. Show all posts
Showing posts with label Mockito. Show all posts

Thursday, 9 March 2017

Mocking new instances with Powermock

Using Powermock it is possible to mock a new instance to avoid unnecessary depth to your unit test. This is relatively unusual in an IoC environment (inversion of control eg spring) because you'd inject the PropertyLoader and therefore mocking would be easy.  However, particularly in legacy code this can be found.

If a class has this method you many not want to traverse into the PropertyLoader.

public class MyClass {

    /**
     * Method to enrich the object with a property applicable for today.
     *
     * @param myObj The object to be enriched
     */
    public void enrichWithProperties(MyObject myObj) {
        final PropertyLoader propertyLoader = new PropertyLoader();
        myObj.setProperty(propertyLoader.getTodaysProperty());
    }
}

It could be that new PropertyLoader() has a whole series of dependencies that you don't want to end up mocking as this will make the unit test really unclear.  Instead you can use Powermock to return a mocked PropertyLoader instance to greatly simply things.



import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.whenNew;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

/**
 * Test class for the .....
 */
@RunWith(PowerMockRunner.class)
@PrepareForTest(MyClass.class)
public class MyClassTest {

    /** The class under test. */
    private MyClass classUnderTest = new MyClass();

    @Test
    public void testEnrichWithProperties() {

        // Arrange
        final String todaysValue = "todaysValue";
        final MyObject myObj = new MyObject();
        final PropertyLoader mockedPropertyLoader = mock(PropertyLoader.class);
        whenNew(PropertyLoader.class).withAnyArguments().thenReturn(mockedPropertyLoader);
        when(mockedPropertyLoader.getTodaysProperty()).thenReturn(todaysValue);

        // Act
        classUnderTest.enrichWithProperties(myObj);

        // Assert
        assertEquals(todaysValue, myObj.getProperty());
    }

}


Note: Unlike the mocking statics, you have to PrepareForTest the class which instantiates the mocked class not the mocked class itself. So above MyClass is prepared not PropertyLoader.

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>