2015-10-10 3 views
5

Я пытаюсь использовать MVP для повышения модульного тестирования и выполнения тестов быстрее (потому что я тестирую логику, а не код Android, поэтому я избегаю использования таких вещей, как RobotElectric).JUnit Scheduler, который не зависит от Android

Но I'm с помощью RXAndroid и ему нужно Looper, чтобы получить Schedulers.io() и AndroidSchedulers.mainThread() и когда я пытаюсь запустить когда-нибудь, как

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

я получаю:

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 

Я пробовал:

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

Но это не сработает, потому что я хочу запускать полные тесты JUnit, а не Robo электрический или эспрессо.

Как это сделать? есть ли какой-нибудь Планировщик, который не потерпит краха из-за этого?

ответ

20

Я также использую планировщиком нить для этого, но в мой тест SetUp и 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(); 
    } 

Будет ли это помогать?

+0

есть ли какой-нибудь крючок для Schedulers.io()? – Caipivara

+0

Есть RxJavaPlugins.getInstance(). Register ...тоже :) – Caipivara

+0

@ danielgomezrico да, но я не использовал его, хотя, если у вас есть возможность вывести прозрение или отредактировать ответ –

3

В нашей практике мы стараемся избегать использования AndroidSchedulers.mainThread() в Presenter, потому что это деталь реализации View. Ты тоже можешь это сделать.

Хотя мы используем Robolectric, поэтому в любом случае это будет работать в наших тестах.

+0

Я немного скептически отношусь к Roboeletric, я закончил использование Immediate Scheduler для тестирования. – Caipivara

+1

@ danielgomezrico, как вы использовали Immediate scheduler для тестирования? Вы все еще используете AndroidScheduelrs.mainThread() вне тестов? Как вы это делаете? Спасибо – drees

+0

@drees Я использую классы инъекций вкуса, у меня есть класс, который использует основные для выпусков prod/debug и использует другой класс в папке вкуса для тестирования. Я все еще использую Schedulers.immediate() для тестирования да. – Caipivara

2

Yup, нет android.jar в тестах юнита означает нет Loopers. Если вы используете Dagger, вы можете ввести макет планировщика в тесты и реального планировщика в исходный код. Вы также можете использовать что-то вроде Mockito, чтобы издеваться над Планировщиком. В противном случае, как предложил @Artem Zinnatullin, Robolectric решает эту проблему. Robolectric 3 очень прост в настройке с Android Studio.

+0

Я пытаюсь избежать Roboelectric, но спасибо. – Caipivara

5

Я закончил тем, что добавил для этого преобразования с использованием «классов впрыска вкуса», у которых есть класс, который использует основной для выпусков prod/debug и использует другой класс в папке тестового вкуса для тестирования Schedulers.immediate().

нормальный ароматизированный класс:

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

Тестирование ароматизированный класс:

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

Затем используйте его с преобразованиями:

mSessionRepository.login(...) 
     .compose(Transformer.applyIoSchedulers()) 
     .subscribe(session -> { }) 
Смежные вопросы