2015-04-14 8 views
10

Ich versuche, einen Test mit Robolectric zu erstellen. Mein Ziel ist es, in der Lage zu sein, die Funktionalität einer Klasse (die zum Beispiel aus einer Bibliothek kommt und ich den Code nicht ändern kann) durch ein benutzerdefiniertes Verhalten zu ersetzen.Robolectric Schatten funktioniert nicht

Ich habe diesen kleinen Test zu simulieren, was ich tun möchte:

@RunWith(RobolectricTestRunner.class) 
@Config(shadows = {ShadowMessenger.class}) 
public class TestShadow { 

    @Test 
    public void testMessenger() { 
     OriginalMessenger messenger = new OriginalMessenger(); 
     String message = messenger.getMessage(); 
     Assert.assertEquals("Shadow messenger", message); 
    } 

    public static class OriginalMessenger { 

     public String getMessage() { 
      return "Original messenger"; 
     } 
    } 

    @Implements(OriginalMessenger.class) 
    public static class ShadowMessenger extends OriginalMessenger { 

     @Implementation 
     public String getMessage() { 
      return "Shadow messenger"; 
     } 
    } 
} 

Im Beispiel OriginalMessenger die Klasse, die in der Bibliothek und stellt eine Standardfunktionalität. Und ShadowMessenger ist die Klasse, die das benutzerdefinierte Verhalten enthält, das ich anwenden möchte, wenn ich OriginalMessenger verwende.

Allerdings, wenn ich den Test ausführen, schlägt es fehl. Der Inhalt von Nachricht ist "Original Messenger". Als ob der ShadowMessenger nie benutzt wurde.

Was mache ich falsch?

+2

Warum einen Schatten machen? Warum nicht "mock" oder "stub" es aus? –

+0

Wie erreiche ich das gleiche Ergebnis mit Mocks und Stubs? –

+0

Oh ich sehe nenick dein Problem gelöst? Sie können EasyMock/PowerMock verwenden, um aus Ihrer Klasse herauszuspielen oder Spock (Robospock). Hier ein Beispiel: https://github.com/jaredsburrows/BurrowsAppsExamples/blob/master/Lib-BurrowsApps/src/test/java/burrows/apps/example/lib/utils/PlayServicesUtilsTest.java. –

Antwort

14

Original können Sie nur Android-Klassen Schatten. Aber mit einem benutzerdefinierten roboelektric Test-Läufer können Sie auch Ihre eigenen Klassen beschatten.

Robolectric 3.1.4 (RobolectricGradleTestRunner wurde vollständig entfernt, so dass Sie die Methode unten in RobolectricTestRunner beschrieben außer Kraft setzen müssen)

@Override 
protected ShadowMap createShadowMap() { 
    return new ShadowMap.Builder() 
     .addShadowClass(OriginalMessenger.class, ShadowMessenger.class, true, true, true) 
     .build(); 
} 

Robolectric 3,0

@Override 
public InstrumentationConfiguration createClassLoaderConfig() { 
    InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder(); 
    builder.addInstrumentedClass(OriginalMessenger.class.getName()); 
    return builder.build(); 
} 

Robolectric 2,4

@Override 
protected ClassLoader createRobolectricClassLoader(Setup setup, SdkConfig sdkConfig) { 
    return super.createRobolectricClassLoader(new ExtraShadows(setup), sdkConfig); 
} 

class ExtraShadows extends Setup { 
    private Setup setup; 

    public ExtraShadows(Setup setup) { 
     this.setup = setup; 
    } 

    public boolean shouldInstrument(ClassInfo classInfo) { 
     boolean shoudInstrument = setup.shouldInstrument(classInfo); 
     return shoudInstrument 
       || classInfo.getName().equals(OriginalMessenger.class.getName()); 
    } 
} 

Beispielprojekt https://github.com/nenick/android-gradle-template/

+0

Schön! Wusste nicht darüber –

+5

Es gibt viele undokumentierte Funktionen;) – nenick

+0

Wenn ich das tue bekomme ich einen StackOverflowError. Weißt du warum es passiert? –