2015-10-10 7 views
5

Ich versuche MVP zu verwenden, um Komponententests zu verbessern und Tests schneller auszuführen (weil ich Logik nicht android Code teste, also vermeide ich Sachen wie RobotElectric zu verwenden).JUnit Scheduler, der nicht von Android abhängig ist

Aber ich bin mit RXAndroid und es braucht Looper Schedulers.io() und AndroidSchedulers.mainThread() zu bekommen und wenn ich versuche, irgendwann wie

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

ich zu laufen bekommen:

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 

Ich habe versucht:

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

Aber es wird nicht funktionieren, weil ich volle JUnit-Tests und nicht Robo ausführen möchte Elektro- oder Espresso-Zeug.

Wie kann ich es erreichen? Gibt es einen Scheduler, der deswegen nicht abstürzt?

Antwort

20

Ich bin auch für den Scheduler-Thread verwendet wird, aber in Mein Test SetUp und 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(); 
    } 

Wird dies helfen?

+0

Gibt es einen Haken für Schedulers.io()? – Caipivara

+0

Es gibt RxJavaPlugins.getInstance(). Registrieren ...auch :) – Caipivara

+0

@danielgomezrico ja, aber ich habe es noch nicht verwendet, wenn Sie haben, können Sie Einblick setzen oder Antwort bearbeiten –

3

In unserer Praxis versuchen wir zu vermeiden, AndroidSchedulers.mainThread() in Presenter zu verwenden, da es ein Detail der View Implementierung ist. Sie können dies auch tun.

Obwohl wir Robolectric verwenden, wird es trotzdem in unseren Tests funktionieren.

+0

Ich bin ein wenig skeptisch über Roboelectric, ich endete mit Immediate Scheduler zum Testen. – Caipivara

+1

@danielgomezrico Wie hast du Immediate Scheduler zum Testen benutzt? Verwenden Sie AndroidScheduelrs.mainThread() weiterhin außerhalb von Tests? Wie machst du die Diktion? Danke – drees

+0

@drees Ich benutze Flavour Injection-Klassen, ich habe eine Klasse, die die wichtigsten für Prod/Debug-Releases verwendet und eine andere Klasse im Flavor-Ordner zum Testen verwenden. Ich benutze noch Schedulers.immiate() zum Testen ja. – Caipivara

2

Yup, keine android.jar in Junit-Tests bedeutet keine Loopers. Wenn Sie Dolch verwenden, können Sie einen Mock-Scheduler in Tests und einen echten Scheduler in den Quellcode einfügen. Sie könnten auch etwas wie Mockito verwenden, um den Scheduler zu verspotten. Ansonsten, wie @Artem Zinnatullin vorgeschlagen hat, löst Robolectric dieses Problem. Robolectric 3 lässt sich sehr einfach mit Android Studio einrichten.

+0

Ich versuche, Roboelectric zu vermeiden, aber danke. – Caipivara

5

Ich habe am Ende mit Transformationen und "Flavour Injection-Klassen" hinzufügen, haben eine Klasse, die die Haupt für Prod/Debug-Releases verwendet und verwenden Sie eine andere Klasse im Test Flavor Ordner zum Testen Schedulers.immediate().

normale aromatisierte Klasse:

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 aromatisiert Klasse:

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

Dann ist es mit Transformationen verwenden:

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