2015-12-04 10 views
7

ho una classe molto semplice che ha una Handler, quando gestisce messaggio che invia di nuovo un nuovo messaggio:Robolectric: eseguire crochet di gestore nel mio caso

public class MyRepeatTask{ 
    … 
    public void startTask() { 
    // send message with delay 5 sec 
    handler.sendMessageDelayed(handler.obtainMessage(…), 5000); 
    } 

    Handler handler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      // I put a log for unit test 
      System.out.println(“handling message …”); 
      // send message with delay again 
      handler.sendMessageDelayed(handler.obtainMessage(…), 5000); 
     } 
    } 
} 

Come vedete sopra, quando startTask() si chiama, il gestore inizia a inviare un messaggio in 5 secondi. Quindi, nel callback handleMessage(), lo handler invia nuovamente un messaggio con ritardo di 5 secondi. Lo scopo di questo è di fare ripetutamente alcune attività (come System.out.println()).

ho testare la classe di cui sopra con Robolectric:

@RunWith(RobolectricTestRunner.class) 
public class MyRepeatTaskTest { 
    @Test 
    public void testStartTask() { 
    MyRepeatTask task = new MyRepeatTask(); 
    task.startTask(); 

    // run looper of ‘handler’ in task 
    ShadowLooper shadowLooper = Shadows.shadowOf(task.handler.getLooper()); 
    shadowLooper.runToEndOfTasks(); 

    // sleep for 30 seconds 
    Thread.sleep(30 * 1000); 
    } 
} 

mi aspetto di vedere i System.out.println() messaggio “handling message …” ogni 5 secondi. Tuttavia, quando eseguo il test, vedo solo il messaggio una volta nel terminale.

sembra che s ‘il handlerLooper ha funzionato solo per un compito, poi si è fermato.

Se ho ragione, come mantenere il looper sempre in esecuzione in Robolectric? Se ho torto, perché vedo solo un messaggio di registro?

========== UPDATE ===========

ho cercato risposta @rds 's, ho sostituito Thread.sleep(30 * 1000); da:

for (int i = 0; i < N; i++){ 
    shadowLooper.runToEndOfTasks(); 
} 

Ora posso vedere N volte "handling message …". MA, l'intero test non sta simulando il ritardo. Ho 5 secondi di ritardo quando invio un messaggio con handler.sendMessageDelayed(handler.obtainMessage(…), 5000), è così che il framework Robolectric non simula affatto questo tipo di messaggio di ritardo ??? Come posso avere il ritardo nel mio test?

risposta

0

Il problema è che quando si chiama runToEndOfTasks(); c'è in questa fase solo un'attività.

Invece di lasciare il thread di prova inattivo, è necessario chiamare shadowLooper.runToEndOfTasks(); N volte per avere N chiamate del gestore.

+0

Questo è anche un test più robusto, ed è per questo che Robolectric funziona così. A seconda del tempo che il tuo codice impiega per eseguire, non sai quante iterazioni saranno eseguite in 30 secondi, ma i test sanno esattamente quante volte è stato chiamato 'runToEndOfTasks()'. – rds

+0

grazie. Vuoi dire che dovrei sostituire il thread sleep con un ciclo for che chiama runToEndOfTasks() N volte? 'for (int i = 0; i user842225

+0

Si prega di consultare il mio aggiornamento nel mio post. – user842225

0

Mi sono imbattuto in problemi simili durante l'implementazione di un download programmato da api-webservice. Ho implementato un timer in aggiunta a un gestore. L'ho usato per fare un compito ogni giorno (o nel tuo caso in alcuni secondi). È anche possibile impostare il numero di volte ...

Timer Reference Android

0

Sembra che stai cercando ShadowLooper#idle(long). Ciò consentirà di far avanzare attentamente il tempo del gestore e asserire se l'attività viene eseguita o meno a intervalli diversi.