2013-01-15 13 views
6

Sto tentando di utilizzare Dagger in un test funzionale Android che eredita ActivityInstrumentationTestCase2.Dagger supporta l'integrazione delle dipendenze per i test ActivityInstrumentationTestCase2

codice

La configurazione è simile al seguente:

@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(); 
}` 

Il metodo OnCreate, che viene licenziato chiamando super.getActivity(), non utilizzare le classi fornite dal TestModule. Ma se eseguo la mia attività manualmente (al di fuori del contesto di test) tutte le classi appropriate sono fornite/iniettate dal mio modulo non test.

+0

Quindi non è facile vedere qui quello che sta succedendo, perché non vediamo quello che stai iniettare nella prova, ecc Si può tagliare e fornire un esempio semplificato dei moduli di produzione e test, che replica questo problema? –

+0

Forse la mia risposta in questo post correlato si aiuta: http://stackoverflow.com/questions/15630589/android-functional-testing-with-dagger?rq=1 – IIIRepublica

risposta

3

ho trovato un modo per utilizzare Pugnale con ActivityInstrumentationTestCase2 creando pigramente il grafico oggetto. Quello che faccio è aspettare di creare l'Object Graph fino alla prima volta in cui una classe vuole essere iniettata, quindi se aggiungi i tuoi moduli prima di chiamare getActivity() (che avvia il ciclo di vita dell'attività per l'attività sottoposta a test) usa nel tuo moduli di test, questo funzionerà. Ecco le relative classi e snippet:

GraphHolder, come suggerisce il nome, contiene l'oggetto ObjectGraph per noi. Effettueremo tutte le chiamate su questa classe anziché direttamente su 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; 
    } 
} 

Aggiungeremo i nostri moduli nella classe Application:

public class MyApplication extends Application { 

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

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

All'interno delle classi che vogliamo iniettare, faremo semplicemente chiamiamo GraphHolder.getInstance().inject(this) piuttosto che ObjectGraph.inject(this)

Nei nostri moduli di test , forniremo gli oggetti da sovrascrivere per il test e aggiungere overrides = true all'annotazione @Module. Questo dice al grafico dell'oggetto di preferire i provider di questo modulo rispetto ad altri se c'è un conflitto.

Poi, nei nostri test:

@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);

Questo codice sta cercando di iniettare le dipendenze create da TestModule nella vostra TestCase al posto del Activity testato. Quello che avrebbe dovuto fare qui è

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

+3

non si può iniettare in un'attività da ActivityInstrumentationTestCase2 anche se devi chiamare getActivity() per ottenere un riferimento all'attività e che lo creerà (chiamando onCreate automaticamente). Pertanto, se si esegue l'iniezione nel metodo onCreate, sarà troppo tardi per iniettare le dipendenze se si tenta di impostarlo da ActivityInstrumentationTestCase2. IMO questo è un enorme difetto in ActivityInstrumentationTestCase2. Puoi invece utilizzare ActivityUnitTestCase. –

Problemi correlati