I have try test button function using Mockito. The code include Layout/SampleActivity/UnitTest major Content:
layout file define:
android:text="testbtnmock"
android:id="@+id/btn_testbtnmock"
android:onClick="testBtnMock"
SampleActivity file define
public void testBtnMock(View view) {
System.out.println("value:"+getInt());
}
public int getInt(){
return 0;
}
UnitTest file define
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)
public class SampleActivityTest {
private SampleActivity sampleActivity;
private Button testBtnMock;
@Before
public void setUp() {
ShadowLog.stream = System.out;
}
@Test
public void testBtnMock() {
sampleActivity = Robolectric.setupActivity(SampleActivity.class);
SampleActivity spySampleActivity = spy(sampleActivity);
when(spySampleActivity.getInt()).thenReturn(100);
//spySampleActivity.testBtnMock(mock(View.class)); //it is working , print 100
testBtnMock = (Button) sampleActivity.findViewById(R.id.btn_testbtnmock);
testBtnMock.performClick(); //it is not work , print 0 ,mock invalid
}
}
My questions are:
spySampleActivity.testBtnMock(mock(View.class));
to trigger the function of testBtnMock(View v)
. It is working and prints 100.testBtnMock.performClick();
doesn't work and prints 0. Why? How to fix it?That is quite easy to explain.
The XML attribute will be used for calling the method via reflection (How does the android Xml attribute android:onClick="..." work behind the scenes?).
So, with some simplification, the context from button will be used and method will be invoked by reflection. Button gets context during inflation and it is the reference to not spy activity. That is why real method called in your test.
When you call the method through the reference to spy activity it works.
How to fix:
Something like:
public class IntegerProvider {
public int getInt(){
return 0;
}
}
public class SampleActivity {
IntegerProvider intProvider;
public void testBtnMock(View view) {
System.out.println("value:" + intProvider.getInt());
}
}
@Test
public void testBtnMock() {
sampleActivity = Robolectric.setupActivity(SampleActivity.class);
IntegerProvider providerMock = mock(IntegerProvider.class);
when(providerMock.getInt()).thenReturn(100);
sampleActivity.intProvider = providerMock;
testBtnMock = (Button) sampleActivity.findViewById(R.id.btn_testbtnmock);
testBtnMock.performClick();
}