JUnit scheduler which is not dependent on Android

I'm trying to use MVP to increase unit testing and run tests faster (because I'm testing logic, not Android code, so I avoid using things like RobotElectric).

But I use RXAndroid, and I need Looper to get Schedulers.io() and AndroidSchedulers.mainThread() , and when I try to run something like

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

I get:

 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 

I tried:

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

But this will not work, because I want to run full JUnit tests, not Roboelectric or Espresso.

How can i do this? Is there any Planner that won't crash because of this?

+5
source share
4 answers

I also use the scheduler thread for this, but in my test SetUp and 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(); } 

Did it help?

+20
source

In the end, I added the use of transformations and taste classes for this class, which have a class that uses the main one for prod / debug releases and uses a different class in the test folder for testing Schedulers.immediate() .

normal flavored class:

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

Flavored Class Testing:

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

Then use it with conversions:

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

In our practice, we try to avoid using AndroidSchedulers.mainThread() in Presenter, because this is a detail of the View implementation. You can also do this.

Although we use Robolectric, so in any case it will work in our tests.

+3
source

Yup, no android.jar in unit tests means no Loopers. If you use Dagger, you can introduce the layout of the scheduler in the tests and the real scheduler in the source code. You can also use something like Mockito to mock the Scheduler. Otherwise, as @Artem Zinnatullin suggested, Robolectric solves this problem. Robolectric 3 is very easy to set up with Android Studio.

+2
source

Source: https://habr.com/ru/post/1233434/


All Articles