Android Instrumentation Tests - UI-Thread Fragen
Ich bin versucht zu schreiben, eine Instrumentation Test für meine Android-app.
Ich in einige seltsame threading Probleme und ich kann nicht scheinen, um eine Lösung zu finden.
Meine Ursprüngliche Test:
@RunWith(AndroidJUnit4.class)
public class WorkOrderDetailsTest {
@Rule
public ActivityTestRule<WorkOrderDetails> activityRule = new ActivityTestRule<>(WorkOrderDetails.class);
@Test
public void loadWorkOrder_displaysCorrectly() throws Exception {
final WorkOrderDetails activity = activityRule.getActivity();
WorkOrder workOrder = new WorkOrder();
activity.updateDetails(workOrder);
//Verify customer info is displayed
onView(withId(R.id.customer_name))
.check(matches(withText("John Smith")));
}
}
Dies führte zu einer
android.Blick.ViewRootImpl$CalledFromWrongThreadException: Nur der original-thread, erstellt einen view hierarchy can touch its views.
...
com.kwtree.kwtree.workorder.WorkOrderDetails.updateDetails(WorkOrderDetails.java:155)
Die einzige Sache, die updateDetails()
Methode tut, ist, einige setText()
Anrufe.
Auf der Suche nach etwas, es schien, wie das hinzufügen eines UiThreadTestRule
und android.support.test.annotation.UiThreadTest
Anmerkung zu meinem test würde das problem zu beheben.
@UiThreadTest:
@RunWith(AndroidJUnit4.class)
public class WorkOrderDetailsTest {
//Note: This is new
@Rule
public UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();
@Rule
public ActivityTestRule<WorkOrderDetails> activityRule = new ActivityTestRule<>(WorkOrderDetails.class);
@Test
@UiThreadTest //Note: This is new
public void loadWorkOrder_displaysCorrectly() throws Exception {
final WorkOrderDetails activity = activityRule.getActivity();
WorkOrder workOrder = new WorkOrder();
activity.updateDetails(workOrder);
//Verify customer info is displayed
onView(withId(R.id.customer_name))
.check(matches(withText("John Smith")));
}
}
java.lang.IllegalStateException: Methode kann nicht aufgerufen werden auf der Hauptanwendungs-thread (über: Haupt)
(Hinweis: Alle Methoden, die in diesem stack-trace sind nicht mein code)
Scheint es zu sein, gibt mir gemischte Ergebnisse... Wenn es benötigt, um ausgeführt werden auf den ursprünglichen thread erstellt hat die Aussicht aber nicht ausführen können, auf dem Haupt-thread, welchen thread soll es ausgeführt werden?
Ich würde wirklich zu schätzen jede Hilfe oder Anregungen!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese instrumentation tests führen Sie in Ihrem eigenen app. Dies bedeutet auch, Sie in Ihren eigenen thread.
Müssen Sie denken Sie an Ihre instrumentation als etwas, das Sie installieren neben der eigentlichen app, so dass Ihr möglich, Interaktionen sind "begrenzt".
Müssen Sie zum aufrufen der Ansicht "alle" Methoden aus dem UIThread /Haupt-thread der Anwendung, so ruft
activity.updateDetails(workOrder);
aus Ihrer Instrumentierung thread ist nicht die Anwendung Haupt-thread. Dies ist der Grund, warum die exception geworfen wird.Führen Sie einfach den code, den Sie brauchen, um zu testen auf Ihrem Haupt-thread wie Sie tun würden, wenn Sie riefen es in Ihrem app von einem anderen thread mithilfe
Mit diesem läuft Ihr test sollte funktionieren.
Den illegalen Zustand Ausnahme, die Sie erhalten zu sein scheint, weil Ihre Interaktion mit der Regel. Die Dokumentation Staaten
Wenn Sie beginnen, /Ihr-Aktivität in
@Before
sollte es auch funktionieren.runOnUiThread
Ansatz funktioniert in Kombination mitgetInstrumentation().waitForIdleSync();
. Die@Before
Ansatz hat nicht funktioniert, leider. Vielen Dank für die Hilfe!Können Sie ausführen Teil Ihrer Prüfung auf dem Haupt-UI-thread mit Hilfe von
UiThreadTestRule.runOnUiThread(Runnable)
:In den meisten Fällen ist es einfacher, zu kommentieren, die test-Methode mit
UiThreadTest
aber es entstehen andere Fehler, wie z.B.java.lang.IllegalStateException: Method cannot be called on the main application thread (on: main)
.FYR, hier ist ein Zitat aus
UiThreadTest
's Javadoc:Bitte beachten Sie
UiThreadTest
(Paketandroid.support.test.annotation
) oben erwähnt unterscheidet sich von (UiThreadTest
(Paketandroid.test
)).Die akzeptierte Antwort ist jetzt veraltet
Der einfachste Weg dies zu erreichen ist einfach mit
UiThreadTest
Android.Test.UIThreadTest is deprecated as of API 24: Android 7.0 (Nougat)
beachten Sie, dass dies nicht die gleiche Anmerkung. Diese Antwort ist mit der Unterstützung der annotation. Dass Sie nicht gelöst werden kann für mich, obwohlAkzeptierte Antwort beschrieben, was passiert ist perfekt.
Als Ergänzung, falls jemand neugierig ist, warum Espresso-Methoden, die touch-UI z.B.
perform(ViewActions ...)
brauchen nicht, das gleiche zu tun, es ist einfach, weil Sie am Ende tut es später für uns.Wenn Sie Folgen Sie
perform(ViewActions ...)
Sie finden es endet wie folgt (inandroid.support.test.espresso.ViewInteraction
):Dass
mainThreadExecutor
selbst kommentiert mit@MainThread
.In anderen Worten, Espresso braucht auch zum spielen mit den gleichen Regeln beschrieben, die von David auf die akzeptierte Antwort.