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.