2015-10-10 16 views
5

MVP'yi ünite testini geliştirmek ve testleri daha hızlı çalıştırmak için kullanıyorum (çünkü robotik mantığı test etmiyorum, böylece RobotElectric gibi şeyleri kullanmaktan kaçınıyorum).JUnit Zamanlayıcı, Android'e bağımlı değildir.

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 

Denedim: Bir ara gibi

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

çalıştırmayı denediğinizde Schedulers.io() ve AndroidSchedulers.mainThread() almak ve RXAndroid ve ihtiyacı olan Looper kullanılarak

Ama Lafınızı olsun

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

Ancak bu işe yaramaz çünkü tam JUnit testleri çalıştırmak istiyorum ve Robo değil elektrik veya Espresso şeyler.

Bunu nasıl yapabilirim? bunun yüzünden çökmeyecek herhangi bir Zamanlayıcı var mı?

cevap

20

ama içinde:

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

Sonra dönüşümleri ile kullanmak Test SetUp ve 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(); 
    } 

Bu yardımcı olur mu?

+0

Schedulers.io() için herhangi bir kanca var mı? – Caipivara

+0

RxJavaPlugins.getInstance() kayıtlıdır ...çok :) – Caipivara

+0

@danielgomezrico evet ama bunu kullanmamıştım, eğer bir fikir verebilir ya da cevabı düzenleyebilir misin –

3

Pratikte, View uygulamasının bir ayrıntı olduğundan, Presenter'da AndroidSchedulers.mainThread() kullanmaktan kaçınmaya çalışıyoruz. Bunu da yapabilirsin.

Robolectric kullanıyor olsak da, yine de testlerimizde çalışacaktır.

+0

Roboeletric hakkında biraz şüpheciyim, test için Hemen Zamanlayıcı'yı kullanarak sona erdim. – Caipivara

+1

@danielgomezrico Test için Hemen zamanlayıcıyı nasıl kullandınız? Hala testlerin dışında AndroidScheduelrs.mainThread() kullanıyor musunuz? Bu nasıl bir şey yapıyorsun? Teşekkürler – drees

+0

@drees Lezzet enjeksiyon sınıfları kullanıyorum, prod/debug sürümleri için ana kullanan ve test için lezzet klasöründe başka bir sınıf kullanan bir sınıfa sahibim. Hala test için Schedulers.immediate() kullanıyorum. – Caipivara

2

Yup, hayır testleri için android.jar yok hayır Döngü anlamına gelir. Hançeri kullanırsanız, sahte bir zamanlayıcıyı testlere ve gerçek bir programlayıcıya kaynak koduna enjekte edebilirsiniz. Zamanlayıcı ile dalga geçmek için Mockito gibi bir şeyi de kullanabilirsiniz. Aksi takdirde, Zematullin'in önerdiği gibi, Robolectric bu problemi çözer. Robolectric 3'ün Android Studio ile kurulumu çok kolaydır.

+0

Roboelectric'ten kaçınmaya çalışıyorum ama teşekkürler. – Caipivara

5

Bunun için dönüşümler ve "aroma enjeksiyon sınıfları" kullanarak ekledim, prod/debug sürümleri için ana sayfayı kullanan ve Schedulers.immediate()'u test etmek için test aroma klasöründe başka bir sınıf kullanan bir sınıfa sahip oldum.

Normal aromalı sınıfı:

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 aromalı sınıfı: Ben de bunun için zamanlayıcı iş parçacığı kullanıyorum

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