7

Come ottenere il riferimento di Attività prima che il suo onCreate venga chiamato. mentre è sotto test. Io uso ActivityTestRule come regola JUnit. La ragione di questo requisito è che voglio iniettare Mock in attività dai test.Come ottenere il riferimento attività prima che il suo oncreate venga chiamato durante i test

public class MyActivity extends Activity{ 

    MyComponent myComponent; 

    @Override 
    public void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 
     if(myComponent==null){ 
      myComponent ... //initialise dagger component 
     } 
     myComponent.inject(this); 
     ... 
    } 

    public void setComponent(MyComponent comp){ 
     this.myComponent = comp; 
    } 
} 

public class MyTest{ 

    @Rule 
    public ActivityTestRule<MyActivity> intentsTestRule = new ActivityTestRule<>(MyActivity.class); 


    MyComponent myFakeComponent; 

    @Before          
    public void setUp() {       
     MyActivity activity = intentsTestRule.getActivity(); 
     activity.setComponent(myFakeComponent); 
    }            

    @Test 
    public void testMethod1(){...} 
} 
+0

Usi 'Dagger'?Se sì, dove inizializzi i moduli di Dagger? – eleven

+0

Lo faccio in setUp() –

risposta

0

Questo codice è completo? Non riesco a vederti mentre crei il grafico del pugnale. Ad ogni modo, quello che faccio nel mio codice, è di avere una classe statica chiamata Injector che crea il grafico per me e può anche iniettare elementi negli oggetti. Quindi, nella mia Application Class lo chiamo per creare il grafico, e tutte le altre attività usano solo il grafico esistente.

Quindi, in un test, è possibile creare una classe di applicazione di prova falsa che inizializza il grafico in un modo diverso, o semplicemente ricrea il grafico chiamando i metodi Injector, prima che l'attività venga creata. Non ho familiarità con ActivityTestRule, quindi non posso aiutare molto con il ciclo di vita di questo test.

Ma assicuratevi di creare un nuovo grafico prima di creare l'attività e lasciare che l'attività utilizzi solo il grafico esistente. Come l'attività accede al grafico? Beh, non lo amo davvero, ma siamo abituati ad accedere alla classe dell'applicazione (con cast esplicito) e chiedergli di iniettare le dipendenze per noi. Questo è il modo in cui gli esempi di Dagger lo fanno anche.

14

Come da documentazione, quello che stai facendo qui è sbagliato.

@Rule 
public ActivityTestRule<MyActivity> intentsTestRule = new ActivityTestRule<>(MyActivity.class); 

MyComponent myFakeComponent; 

@Before          
public void setUp() {       
    MyActivity activity = intentsTestRule.getActivity(); 
    activity.setComponent(myFakeComponent); 
}    

Poiché,

Questa regola fornisce test funzionale di una singola attività. L'attività in prova verrà avviata prima di ogni prova annotata con Test e prima dei metodi annotati con @Before. Sarà terminato al termine del test e i metodi annotati con After sono terminati. Durante la durata del test sarai in grado di manipolare direttamente la tua attività.

Tuttavia!

protected void beforeActivityLaunched() 

override questo metodo per eseguire qualsiasi codice che deve essere eseguito prima di creare la vostra attività e ha lanciato. Questo metodo viene chiamato prima di ogni metodo di prova, , incluso qualsiasi metodo annotato con @Before.

Pertanto, se si sposta l'inizializzazione del MainActivityComponent al di fuori della attività in un luogo che è mockable, allora sarete in grado di sperimentare insieme prima che venga creata l'attività principale.

EDIT:

Un'altra possibile soluzione è quella di avviare pigramente l'attività come da link.

@Rule 
public ActivityTestRule<NoteDetailActivity> mNoteDetailActivityTestRule = 
     new ActivityTestRule<>(NoteDetailActivity.class, true /* Initial touch mode */, 
       false /* Lazily launch activity */); 

@Before 
public void intentWithStubbedNoteId() { 
    // Add a note stub to the fake service api layer. 
    FakeNotesServiceApiImpl.addNotes(NOTE); 

    // Lazily start the Activity from the ActivityTestRule this time to inject the start Intent 
    Intent startIntent = new Intent(); 
    startIntent.putExtra(NoteDetailActivity.EXTRA_NOTE_ID, NOTE.getId()); 
    mNoteDetailActivityTestRule.launchActivity(startIntent); 

    registerIdlingResource(); 
} 
0

Ecco il mio codice di esempio per che:

public class TestClass { 

    @Rule 
    public ActivityTestRule<T> activityRule = new ActivityTestRule<T>(type) { 
      @Override 
      protected void beforeActivityLaunched() { 
       //TODO inject mocks, setup stubs etc.. 
      } 
     }; 
    } 

    @Before 
    public void before() { 
     activityRule.getActivity(); 
    } 

    @Test 
    public void myTest() { 
     //... 
    } 


} 
Problemi correlati