2015-10-10 13 views
5

Sto tentando di utilizzare MVP per migliorare i test delle unità ed eseguire test più velocemente (perché sto testando la logica non il codice di Android, quindi evito di usare cose come RobotElectric).JUnit Scheduler che non dipende da Android

Ma sto usando RXAndroid e ha bisogno Looper per ottenere Schedulers.io() e AndroidSchedulers.mainThread() e quando provo a correre qualche volta come

class Phone { 
    public Observable<> sendSms(String number){ 
     //... 
    } 
} 

Phone.getInstance().sendSms(phoneNumber) 
       .subscribeOn(Schedulers.io()) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(phone -> { 
        mView.dismissProgress(); 
        mView.startCodeView(phone); 
       }, error -> { 
        mView.dismissProgress(); 
        mView.showError(error); 
       }); 

ottengo:

Caused by: java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details. 
at android.os.Looper.getMainLooper(Looper.java) 
at rx.android.schedulers.AndroidSchedulers.<clinit>(AndroidSchedulers.java:27) 
... 28 more 

ho provato:

android { 
    // ... 
    testOptions { 
    unitTests.returnDefaultValues = true 
    } 
} 

Ma non funzionerà perché voglio eseguire test JUnit completi e non Robo roba elettrica o Espresso.

Come posso realizzarlo? c'è qualche schedulatore che non si bloccherà a causa di questo?

risposta

20

Sono anche utilizzando filo di pianificazione per questo, ma in il mio test SetUp e TearDown.

@Before 
    public void setUp() throws Exception { 
     RxAndroidPlugins.getInstance().registerSchedulersHook(new RxAndroidSchedulersHook() { 
      @Override 
      public Scheduler getMainThreadScheduler() { 
       return Schedulers.immediate(); 
      } 
     }); 
} 

@After 
    public void tearDown() { 
     RxAndroidPlugins.getInstance().reset(); 
    } 

Questo sarà di aiuto?

+0

c'è qualche hook per Schedulers.io()? – Caipivara

+0

C'è RxJavaPlugins.getInstance(). Register ...troppo :) – Caipivara

+0

@danielgomezrico sì ma non l'ho usato però, se hai puoi inserire intuizione o modificare risposta –

3

Nella nostra pratica, si tenta di evitare l'uso di AndroidSchedulers.mainThread() in Presenter perché è un dettaglio dell'implementazione di View. Puoi farlo anche tu.

Anche se usiamo Robolectric, comunque funzionerà nei nostri test.

+0

Sono un po 'scettico su Roboeletric, ho finito con l'utilizzo di Immediate Scheduler per i test. – Caipivara

+1

@danielgomezrico come hai utilizzato lo scheduler immediato per i test? Stai ancora utilizzando AndroidScheduelrs.mainThread() al di fuori dei test? Come stai facendo la distorsione? Grazie – drees

+0

@drees Sto usando le classi di iniezione di sapore, ho una classe che usa il principale per le versioni prod/debug e uso un'altra classe nella cartella di sapori per i test. Sto ancora usando Schedulers.immediate() per testare sì. – Caipivara

2

Sì, no android.jar nei test di junit non significa Loopers. Se usi Dagger puoi iniettare un programma di simulazione in test e un vero programmatore nel codice sorgente. Puoi anche usare qualcosa come Mockito per prendere in giro lo Scheduler. Altrimenti, come suggerito da @Artem Zinnatullin, Robolectric risolve questo problema. Robolectric 3 è molto facile da configurare con Android Studio.

+0

Sto cercando di evitare il roboelettrico, ma grazie. – Caipivara

5

Ho finito per aggiungere le trasformazioni e le "classi di iniezione di sapore" per questo, ho una classe che utilizza il principale per prod/debug e usa un'altra classe nella cartella di prova per test Schedulers.immediate().

normale classe aromatizzato:

public class Transformer { 

    public static <T> Observable.Transformer<T, T> applyIoSchedulers() { 
    return observable -> observable.subscribeOn(getIoScheduler()) 
     .observeOn(getMainScheduler()); 
    } 

    private static Scheduler getIoScheduler() { 
    return Schedulers.io(); 
    } 

    private static Scheduler getMainScheduler() { 
    return AndroidSchedulers.mainThread(); 
    } 
} 

Test classe aromatizzato:

public class Transformer { 

    public static <T> Observable.Transformer<T, T> applyIoSchedulers() { 
    return observable -> observable.subscribeOn(getIoScheduler()) 
     .observeOn(getMainScheduler()); 
    } 

    private static Scheduler getIoScheduler() { 
    return Schedulers.immediate() ; 
    } 

    private static Scheduler getMainScheduler() { 
    return Schedulers.immediate() ; 
    } 
} 

Quindi utilizzare con trasformazioni:

mSessionRepository.login(...) 
     .compose(Transformer.applyIoSchedulers()) 
     .subscribe(session -> { })