3

Ich habe versuchen, Test-Taste Funktion mit Mockito. Der Code enthalten Layout/SampleActivity/Unittest Haupt Inhalt:btn.performClick() Unable Mock-Objekt, aber Aktivität Anruf die Funktion kann

Layout-Datei definieren:

android:text="testbtnmock" 
android:id="@+id/btn_testbtnmock" 
android:onClick="testBtnMock" 

SampleActivity Datei

public void testBtnMock(View view) { 
    System.out.println("value:"+getInt()); 
} 

public int getInt(){ 
    return 0; 
} 

Unittest Datei

@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 
    } 
} 
definieren definieren

Meine Fragen sind:

  1. warum spySampleActivity.testBtnMock(mock(View.class)); mit der Funktion von testBtnMock(View v) auszulösen. Es funktioniert und druckt 100.
  2. , aber mit testBtnMock.performClick(); funktioniert nicht und druckt 0. Warum? Wie man es repariert?

Antwort

0

Das ist ziemlich einfach zu erklären.

Das XML-Attribut wird für den Aufruf der Methode über die Reflektion verwendet (How does the android Xml attribute android:onClick="..." work behind the scenes?).

Also, mit etwas Vereinfachung wird der Kontext von Schaltfläche verwendet und Methode wird durch Reflexion aufgerufen. Button bekommt Kontext während der Inflation und es ist der Hinweis, keine Spionageaktivitäten durchzuführen. Deshalb hat in Ihrem Test eine echte Methode aufgerufen.

Wenn Sie die Methode über den Verweis auf Spionageaktivität aufrufen, funktioniert es.

Wie zu beheben:

  1. eine Klasse extrahieren, die es für die Bereitstellung integer
  2. Mock verantwortlich ist und injiziert in Test

Etwas wie:

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(); 
}