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 ClasspublicclassExampleClassextendsScreen {publicintgetHeaderView() {// Lets say we have a generic method which provides different result base on the provided idfinalTextView textView =findViewById(ViewFactory.text_view);textView.setText("Header");finalImageView imageView =findViewById(ViewFactory.image_view);imageView.setImage(BitmapFactory.getUserProfileImage());returnnewHStack(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})publicclassExampleClassTest {privateExampleClass classUnderTest; @BeforepublicvoidsetUp() throwsException {// Create constructor of ExampleClass classUnderTest =newExampleClass(); } @TestpublicvoidgetHeaderView_shoudReturnHStack() throwsNoSuchMethodException {// GivenPowerMockito.replace(View.class.getDeclaredMethod("findViewById",int.class)).with(newInvocationHandler() { @OverridepublicObjectinvoke(Object proxy,Method method,Object[] args) throwsThrowable {finalint viewId = (int) args[0];if (viewId ==ViewFactory.text_view) {// return mock of TextViewreturnMockito.mock(TextView.class); } elseif (viewId ==ViewFactory.image_view) {// return mock of ImageViewreturnMockito.mock(ImageView.class); }// else you can call real method as wellreturnmethod.invoke(proxy, args); } });// WhenfinalHStack 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.