4

Ich führe Espresso-Tests auf meiner Android-Anwendung. Der Test ist flockig. Es kann zuverlässig feststellen, dass das Datenmodell aktualisiert ist. Mein Problem ist, dass die ViewMatchers den gleichen Wert in der Ansicht nicht übereinstimmen können, da die ViewDataBinding die Ansichten noch nicht aktualisiert hat. (Zumindest die meiste Zeit des Tests läuft.)Wie kann ich Espresso warten lassen, bis Data Binding die Ansicht mit dem Datenmodell aktualisiert hat?

Gibt es so etwas wie eine IdlingResource, die inaktiv wird, wenn die ViewDataBinding keine ausstehenden Änderungen in der Ansicht hat?

My Work-around ist eine Kombination executePendingBindings von() aufrufen und ein kleiner Thread.sleep (...)

+0

'executePendingBindings' sollte ausreichen, um loszuwerden: sofort wird ausgeführt die Bindung, wenn diese Methode aufgerufen wird, und nicht während des nächsten Rahmens von' Choreographer' – pskink

+0

That war auch mein erster Gedanke. Es stellt sich jedoch heraus, dass der Test auf dem AndroidJUnit-Thread ausgeführt wird und dass executePendingBindings auf dem MainThread ausgeführt werden muss. Das Planen auf dem Main ist nicht schnell genug oder blockiert genug für eine fehlgeschlagene Assertion im AndroidJUnit-Thread. – Rene

+0

Haben Sie eine Lösung gefunden? Ich habe ein ähnliches Problem, wo während der Espressotests falsche Werte an die Datenbindung übergeben werden, aber wenn ich einen Unterbrechungspunkt hinzufüge und einen Moment warte, werden die korrekten Werte gesendet, die Ansichten werden richtig verknüpft und Espresso findet die Ansicht –

Antwort

1

Der Fehlerbericht erwähnte Reflexion mit ViewDataBinding.USE_CHOREOGRAPHER-false für die Tests zu ändern, hier so ist die Lösung kam ich mit nach oben:

public static void setFinalStatic(Field field, Object newValue) throws Exception { 
    field.setAccessible(true); 

    Field modifiersField; 
    try { 
     modifiersField = Field.class.getDeclaredField("accessFlags"); 
    } catch(NoSuchFieldException e) { 
     //This is an emulator JVM ¯\_(ツ)_/¯ 
     modifiersField = Field.class.getDeclaredField("modifiers"); 
    } 
    modifiersField.setAccessible(true); 
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 

    field.set(null, newValue); 
} 

Dann einfach definiert eine ActivityTestRule für die Aktivität im Test, und seine beforeActivityLaunched() außer Kraft setzen. Dies ist erforderlich, bevor die Aktivität gestartet wird (im Gegensatz zu einer @Before Annotation), da ViewDataBinding eine Looper initialisiert, wenn sie CHOREOGRAPHER nicht verwendet.

@Override 
protected void beforeActivityLaunched() { 
    super.beforeActivityLaunched(); 
    //Because we are using data-binding, we avoid using CHOREOGRAPHER 
    try { 
     ReflectionUtils.setFinalStatic(
      ViewDataBinding.class.getDeclaredField("USE_CHOREOGRAPHER"), false); 
    } catch (Exception e) { 
     Assert.fail(e.getMessage()); 
    } 
} 

Auf diese Weise können Sie davon Thread.sleep()

+0

Funktioniert nicht für mich. Dies schlägt mit "NoSuchFieldException" für "accessFlags" fehl. Aber ich sehe accessFlags auf Feldklasse von Android. Nicht sicher, warum es für mich scheitert. Ich habe es auf Lollipop-Emulator ausgeführt. – rpattabi

+0

@rpattabi Sie könnten auch "modifiers" vor "accessFlags" ausprobieren, wie hier [hier] beschrieben (https://code.google.com/p/android/issues/detail?id=220247#c4). Lass es mich wissen, wenn das funktioniert. Ich hätte feststellen müssen, dass diese Lösung bei der Verwendung eines tatsächlichen Geräts funktioniert hat, so dass es Sinn machen würde, dass es beim Ausführen der Tests in einem Emulator jvm fehlschlagen würde. – verybadalloc

+0

Ich schrieb die Informationen, die Sie in den Link zur Verfügung gestellt: - "Modifiers" ist für Desktop-JVM und "AccessFlags" ist für Android-JVM. Keiner von ihnen arbeitet für mich. – rpattabi

Verwandte Themen