web-dev-qa-db-de.com

Android JUnit Testing ... So erwarten Sie eine Ausnahme

Ich versuche, einige Tests mit dem integrierten Test-Framework von Android Junit zu schreiben. Ich habe ein Problem mit einem Test, bei dem ich eine Ausnahme erwarte. In JUnit lauten die Anmerkungen für die Testmethode: 

@Test(expected = ArithmeticException.class)

In Android schlägt dieser Test jedoch mit einer ArithmeticException fehl.

Ich verstehe, dass die Android-Implementierung nur eine Teilmenge von JUnit 3 ist und nicht einmal die Annotation @Test zulässt (muss @SmallTest, @MediumTest oder @LargeTest sein, und keine davon erlaubt das 'Erwartete = ..'. parameter), aber dies scheint ein ziemlich bedeutender Test zu sein, und es scheint, als würde das Android-Testframework ernsthaft fehlen, wenn es diese Funktion nicht hätte.

Hinweis: Ich habe dies getestet, indem ich die JUnit-Dose zum Projekt und die Anmerkungen zu meinen Testmethoden hinzugefügt habe. Es ist für mich sinnvoll, warum die Anmerkungen vollständig ignoriert werden, da das Android-Framework (Runner?) Nicht nach dieser Anmerkung sucht und diese einfach ignoriert. Grundsätzlich suche ich nur nach dem "richtigen" Weg, dies im Rahmen zu tun. 

42
Gimbl

Die Standardsprache für Junit 3 für diese Art von Test lautete:

public void testThatMethodThrowsException()
{
  try
  {
    doSomethingThatShouldThrow();
    Assert.fail("Should have thrown Arithmetic exception");
  }
  catch(ArithmeticException e)
  {
    //success
  }
}
59

Jetzt ist JUnit4 über Android SDK verfügbar (siehe Android-Test-Kit ).

Update : Es ist jetzt offiziell am d.Android.com :

Der AndroidJUnitRunner ist ein neuer entbündelter Testläufer für Android , Der Teil der Android Support Test Library ist und Über das Android Support Repository heruntergeladen werden kann. Der neue Läufer enthält Alle Verbesserungen von GoogleInstrumentationTestRunner und fügt weitere Funktionen hinzu:

  • JUnit4-Unterstützung
  • Instrumentation Registry für den Zugriff auf Instrumentation, Context und Bündelargumente
  • Testen Sie die Filter @SdkSupress und @RequiresDevice
  • Test-Timeouts
  • Scherben von Tests
  • RunListener-Unterstützung zum Ankoppeln an den Testlauf-Lebenszyklus
  • Aktivitätsüberwachungsmechanismus ActivityLifecycleMonitorRegistry

Also JUnit4-Stil für Ausnahmetests mit erwarteter Annotation:

@Test(expected= IndexOutOfBoundsException.class) 
public void empty() { 
     new ArrayList<Object>().get(0); 
}

oder erwartete Ausnahmeregeln:

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void shouldTestExceptionMessage() throws IndexOutOfBoundsException {
    List<Object> list = new ArrayList<Object>();

    thrown.expect(IndexOutOfBoundsException.class);
    thrown.expectMessage("Index: 0, Size: 0");
    list.get(0); // execution will never get past this line
}

ist auch möglich.

Weitere Informationen zum Einrichten der Test-Support-Bibliothek finden Sie unter offizielle Dokumentation .

24
sandrstar

Ich habe nach guten Lösungen gesucht, aber keine der Lösungen war für mich wirklich zufriedenstellend. Also habe ich meine eigene erstellt.

public final void assertThrows(VoidFunction v, Class<? extends Exception> e) {
    try {
        v.call();
    } catch (Exception ex) {
        if (!ex.getClass().equals(e)) {
            Assert.fail();
        }
        // Do nothing, basically succeeds test if same exception was thrown.
        return;
    }

    // Fails if no exception is thrown by default.
    Assert.fail();
}

Wobei VoidFunction eine einfache Schnittstelle ist:

@FunctionalInterface
public interface VoidFunction {
    void call();
}

Dies wird zum Beispiel wie folgt verwendet:

@Test
public void testFoo() {
    assertThrows(() -> foo.bar(null)), NullPointerException.class);
    assertThrows(() -> foo.setPositiveInt(-5)), IllegalArgumentException.class);
    assertThrows(() -> foo.getObjectAt(-100)), IndexOutOfBoundsException.class);
    assertThrows(new VoidFunction() {
            @Override
            public void call() {
                foo.getObjectAt(-100);
            }
        }, IndexOutOfBoundsException.class); // Success
    assertThrows(new VoidFunction() {
                @Override
                public void call() {
                    throw new Exception();
                }
            }, NullPointerException.class); // Fail

}

Ich habe einen Aufruf ohne Lambda hinzugefügt, dies macht es manchmal einfacher, den Code zu verstehen, zumindest für mich. Einfach zu verwenden und erlaubt mehrere Ausnahmebefehle in der ONE-Methode. 

1
Lurr