2013-01-15 8 views
6

Ich versuche Dagger in einem Android-Funktionstest zu verwenden, der ActivityInstrumentationTestCase2 erbt.Unterstützt Dolch Dependance-Injektion für ActivityInstrumentationTestCase2 Tests

Der Setup-Code sieht wie folgt aus:

@Override 
protected void setUp() { 
    // TODO Auto-generated method stub 
    try { 
     super.setUp(); 
    } catch (Exception e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    ObjectGraph.create(new TestModule()).inject(this); 
    this.activity = super.getActivity(); 
}` 

Die OnCreate-Methode, die durch den Aufruf super.getActivity() abgefeuert wird, verwendet nicht die von der Testmodule bereitgestellten Klassen. Aber wenn ich meine Aktivität manuell ausführe (außerhalb des Testkontexts), werden alle geeigneten Klassen von meinem Nicht-Testmodul bereitgestellt/injiziert.

+0

So ist es nicht einfach, hier zu sehen, was los ist, weil wir nicht sehen, was Sie in den Test sind Injektion etc. Können Sie trimmen und bieten Ein vereinfachtes Beispiel für Ihre Produktions- und Testmodule, die dieses Problem reproduzieren? –

+0

meine Antwort in diesem verwandten Beitrag Vielleicht helfen Ihnen: http://stackoverflow.com/questions/15630589/android-functional-testing-with-dagger?rq=1 – IIIRepublica

Antwort

3

ich einen Weg gefunden, Dolch zu verwenden, um mit ActivityInstrumentationTestCase2 von lazily Objektgraphen zu schaffen. Ich warte darauf, den Objektgraphen bis zum allerersten Mal zu erstellen, an dem eine Klasse injiziert werden soll, solange Sie Ihre Module vor dem Aufruf von getActivity() hinzufügen (wodurch der Aktivitätslebenszyklus für die zu testende Aktivität gestartet wird) und overrides = true in Ihrem Testmodule, das wird funktionieren. Hier sind die relevanten Klassen und Schnipsel:

GraphHolder, wie der Name schon sagt, hält das ObjectGraph Objekt für uns. Wir werden alle Anrufe an diese Klasse vornehmen anstatt direkt an ObjectGraph.

public class GraphHolder { 

    private static GraphHolder sInstance; 

    private Object[] mModules; 
    private ObjectGraph mGraph; 

    private GraphHolder() { 
    } 

    public static GraphHolder getInstance() { 
     if (sInstance == null) { 
      sInstance = new GraphHolder(); 
     } 

     return sInstance; 
    } 

    public void inject(Object object) { 
     if (mGraph == null) { 
      create(); 
     } 

     mGraph.inject(object); 
    } 

    public <T> T get(Class<T> type) { 
     if (mGraph == null) { 
      create(); 
     } 

     return mGraph.get(type); 
    } 

    public void addModules(Object... modules) { 
     if (mGraph != null) { 
      mGraph.plus(modules); 
     } else { 
      if (mModules == null) { 
       mModules = modules; 
      } else { 
       mModules = concatenate(mModules, modules); 
      } 
     } 
    } 

    private void create() { 
     mGraph = ObjectGraph.create(mModules); 
     mModules = null; 
    } 

    private Object[] concatenate(Object[] a, Object[] b) { 
     int aLength = a.length; 
     int bLength = b.length; 

     Object[] c = new Object[aLength + bLength]; 
     System.arraycopy(a, 0, c, 0, aLength); 
     System.arraycopy(b, 0, c, aLength, bLength); 

     return c; 
    } 
} 

Wir werden unsere Module in der Application Klasse hinzufügen:

public class MyApplication extends Application { 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     GraphHolder.getInstance().addModules(getModules()); 
    } 

    Object[] getModules() { 
     return new Object[]{ 
       // your modules here 
     }; 
    } 
} 

Innerhalb der Klassen, die wir injizieren wollen, müssen wir einfach GraphHolder.getInstance().inject(this) nennen anstatt ObjectGraph.inject(this)

In unserem Testmodule stellen wir die Objekte bereit, die wir zum Testen überschreiben möchten, und fügen overrides = true zur @Module Annotation hinzu. Dies weist das Objektdiagramm an, die Anbieter dieses Moduls gegenüber anderen zu bevorzugen, wenn es einen Konflikt gibt.

Dann in unseren Tests:

@Inject Foo mFoo; 

@Override 
public void setUp() { 
    super.setUp(); 
    GraphHolder.getInstance().addModules(new TestFooModule()); 
    GraphHolder.getInstance().inject(this); // This is when the object graph will be created 
} 
1

ObjectGraph.create(new TestModule()).inject(this);

Dieser Code versucht, Abhängigkeiten von Testmodule in der Testcase statt der getesteten Aktivität erstellt zu injizieren. Was würden Sie haben hier zu tun ist,

ObjectGraph.create(new TestModule()).inject(this.activity);

+3

Sie in eine Aktivität nicht injizieren können aus ActivityInstrumentationTestCase2 though, weil Sie getActivity() aufrufen müssen, um eine Referenz auf die Aktivität zu erhalten, und diese erstellt es (Aufruf von onCreate automatisch). Wenn Sie also in der onCreate-Methode injizieren, ist es zu spät, Abhängigkeiten zu injizieren, wenn Sie versuchen, dies über ActivityInstrumentationTestCase2 einzurichten. IMO das ist ein großer Fehler in ActivityInstrumentationTestCase2. Sie können stattdessen ActivityUnitTestCase verwenden. –