2016-02-19 7 views
27

Mockito erstellt eine Proxy-Instanz, wenn etwas ausgespäht wird. Gibt es nun eine Möglichkeit, Setter, die dann auf dieser Proxy-Instanz ausgeführt werden, an die reale Instanz weiterzuleiten, die sich dahinter befindet?Wie man eine Aktivität richtig ausspioniert

Begründung: Ich habe eine Objektinstanz, die ich nicht vollständig unter meiner Kontrolle habe, d. H. Eine Android-Aktivität. Ich kann die meisten Teile meiner App die Proxy-Version geben und das läuft gut wie, ist aber, weil ich den Spion/Proxy sehr früh während der Erstellungsphase der Aktivität erstellen muss, ist es noch nicht vollständig instanziiert, z. Der Basiskontext ist nicht angehängt. Dies geschieht auf der Proxy-Instanz und wird natürlich nicht von der Aktivitätsinstanz selbst verwendet (die sich selbst über Activity.this referenziert). Das Endergebnis ist, dass dies zu allen Arten von Abstürzen führt, da die Ressourcenauflösung über diesen Basiskontext geschieht, so dass die interne Fragment-Maschinerie NPEs und mehr wirft. Hier

ist ein Code:

public class CustomAndroidJUnitRunner extends AndroidJUnitRunner { 
    @Override 
    public Activity newActivity(ClassLoader cl, String className, Intent intent) 
      throws InstantiationException, IllegalAccessException, ClassNotFoundException { 
     Activity activity = super.newActivity(cl, className, intent); 
     return maybeStubSomeDelegate(activity); 
    } 

    private Activity maybeStubSomeDelegate(Activity activity) { 
     if (!(activity instanceof SomeDelegate)) { 
      return activity; 
     } 
     Activity spiedActivity = spy(activity); 
     doReturn(SomeDelegateMock.getInstance()) 
      .when((SomeDelegate) spiedActivity) 
      .getDelegate(); 
     return spiedActivity; 
    } 
} 

Ich bin ahnungslos - irgendwelche Ideen?

+0

Warum Sie nicht verwenden Espresso: https://google.github.io/android-testing-support-library/docs/espresso/ So können Sie die Aktivität auch steuern können. –

+0

Ich benutze bereits Espresso, das hat nichts mit meiner Frage zu tun. –

+0

fügt eine @VisibleForTesting-Methode setDelegate() zu Ihrer Aktivität nicht in Frage? Ich denke, jeder Ansatz, bei dem Spione der Aktivität injiziert werden, hat immer einen Rand, in dem es nicht funktioniert. – jdonmoyer

Antwort

0

Sie können Robolectric verwenden Sie Ihre eigenen Proxy zu erstellen (oder als Robolectric sie „Schatten“ nennt), um Ihre Aktivität,

Wenn Sie die Proxy erstellen können Sie Ihre eigenen Setter erstellen, die die realen Objekt Methoden auslösen können,

Wie ein Schatten Beispiel erstellen:

@Implements(Bitmap.class) 
public class MyShadowBitmap { 

@RealObject private Bitmap realBitmap; 
private int bitmapQuality = -1; 

@Implementation 
public boolean compress(Bitmap.CompressFormat format, int quality, OutputStream stream) { 
    bitmapQuality = quality; 
    return realBitmap.compress(format, quality, stream); 
} 

public int getQuality() { 
    return bitmapQuality; 
} 
} 
} 

wenn die @RealObject ist Ihr richtiges Beispiel

um dies zu verwenden s hadow mit Robolectric Test-Runner eine neue Testklasse wie folgt definieren:

shadowOf() 

Und in jedem Fall, hier ist s Link zu Robolectric:

@RunWith(RobolectricTestRunner.class) 
@Config(shadows = MyShadowBitmap.class) 
public class MyTestClass {} 

die aktuelle Schatteninstanz die Methode verwenden, um ziehen

http://robolectric.org/custom-shadows/

+0

Dies könnte für Unit-Tests nützlich sein, aber ich sprach tatsächlich über Instrumentierungstests :) –

+0

Auch nützlich für Instrumentierungstests (vorausgesetzt, Sie möchten nicht, dass sie auf dem Device \ Emulator laufen) –