PowerMockito.replace()

stub() works best when we don't care about the parameters and want same result irrespective of parameter passed.

With replace() we can go one step ahead of stub(), depending upon the supplied parameters, we can return different results. Let's see another similar example:

// Example Source Class
public class ExampleClass extends Screen {
    public int getHeaderView() {
        // Lets say we have a generic method which provides different result base on the provided id
        final TextView textView = findViewById(ViewFactory.text_view);
        textView.setText("Header");
        final ImageView imageView  = findViewById(ViewFactory.image_view);
        imageView.setImage(BitmapFactory.getUserProfileImage());
        return new HStack(textView, imageView);
    }
}

Now, if we want to test our method with dynamic values, maybe you need to return different values based on parameter.

@RunWith(PowerMockRunner.class)
@PrepareForTest({
    ExampleClass.class
})
public class ExampleClassTest {

    private ExampleClass classUnderTest;

    @Before
    public void setUp() throws Exception {
        // Create constructor of ExampleClass
        classUnderTest = new ExampleClass();
    }

    @Test
    public void getHeaderView_shoudReturnHStack() throws NoSuchMethodException {
        // Given
        PowerMockito.replace(View.class.getDeclaredMethod("findViewById", int.class)).with(new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                final int viewId = (int) args[0];

                if (viewId == ViewFactory.text_view) {
                    // return mock of TextView
                    return Mockito.mock(TextView.class);
                } else if (viewId == ViewFactory.image_view) {
                    // return mock of ImageView
                    return Mockito.mock(ImageView.class);
                }
                // else you can call real method as well
                return method.invoke(proxy, args);
            }
        });

        // When
        final HStack actualResult = classUnderTest.getHeaderView();

        Assert.assertNotNull(actualResult);
    }
}

Note: keep in mind, if you need to manipulate behavior (byte code) of any class, as we are doing in case of replace method, we need to add ExampleClass.class in @PrepareForTest.

Last updated