如何测试复杂的RxJava Observables

时间:2016-09-07 11:15:13

标签: android unit-testing rx-java reactive-programming

我在我的android项目中使用RxJava,我实际上开始对我的代码进行单元测试。

我有以下Observable方法,我将去测试

private Observable<Boolean> changeMyString (@NonNull String testString) {
    return OneClass
        .doSth1(testString)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .flatMap(testString2 -> Observable.create(
            subscriber -> {
                manager.setTestString2(testString2);
                AnotherClass
                    .doSth2(testString2)
                    .subscribe(
                        testString3 -> {
                            manager.setTestString3(testString3);
                            subscriber.onNext(success);
                        },
                        subscriber::onError,
                        subscriber::onCompleted
                    );
            }
        ));

OneClass.java doSth1(String testString)

private Observable<Object> doSth1 (@NonNull String testString) {
    return Observable.create(subscriber -> {
        try {
            testString = "CHANGEDSTRING"
            subscriber.onNext(testString);
            subscriber.onCompleted();
        }
        catch (Exception e) {
            subscriber.onError(e);
        }
    });
}

AnotherClass.java doSth2(Object someObject)

    public Observable<String> doSth2 (@NonNull Object someObject) {
    return Observable.create(subscriber -> {
        String changeText = preferences.getString(ANYSTRING, null); //preferences = SharedPrefences
        if (StringHelper.isEmpty(changeText)) {
            subscriber.onCompleted();
            return;
        }
        try {
            String finishedString = "WE ARE DONE! " + someObject.toString();
            subscriber.onNext(finishedString);
            subscriber.onCompleted();
        }
        catch (Exception e) {
            subscriber.onError(e);
        }
    });
}

我的测试用例如下所示:

TestSubscriber<Boolean> testSubscriber = new TestSubscriber<>();
ClassToTest.changeMyString("TESTSTRING").subscribe(testSubscriber);

当我调试我的代码时,它没有到达此部分:

...
.flatMap(testString2 -> Observable.create(
        subscriber -> {
            manager.setTestString2(testString2);
            AnotherClass
                .doSth2(testString2)
                .subscribe(
                    testString3 -> {
                        manager.setTestString3(testString3);
                        subscriber.onNext(success);
                    },
                    subscriber::onError,
                    subscriber::onCompleted
                );
        }
    ));

如何为此案例编写单元测试?我无法弄明白,为什么它不起作用......

感谢您的帮助!

阿尔

2 个答案:

答案 0 :(得分:2)

您可能希望将其注入并使用TestScheduler而不是直接使用调度程序。它将允许你控制执行。 (对于单元测试,处理其他调度程序可能很复杂)

有关TestSchedulerHow to use TestScheduler in RxJava

的详细信息
 class YourClass {

        private final Scheduler ioScheduler;
        private final Scheduler uiScheduler;

        public YourClass(Scheduler ioScheduler, Scheduler uiScheduler) {
               this.ioScheduler = ioScheduler;
               this.uiScheduler = uiScheduler;
        }

        private Observable<Boolean> changeMyString (@NonNull String testString) {
         return OneClass.doSth1(testString)
                        .subscribeOn(ioScheduler)
                        .observeOn(uiScheduler)
                        .doOnNext(str -> manager.setTestString2(str))
                        .flatMap(testString2 -> AnotherClass
                        .doSth2(testString2))
                        .doOnNext(str -> manager.setString3(str));
         }
 }

然后在您的测试中,您可以注入TestScheduler

   @Test
   public void example() {
          TestScheduler ui = new TestScheduler();
          TestScheduler io = new TestScheduler();
         YourClass hello = new YourClass(io, ui);
           TestSubscriber subscriber = new TestSubscriber();
           hello.changeMyString("stuff").subscribe(subscriber); 

         io.advanceByTime(2, SECONDS);
         ui.advanceByTime(2, SECONDS);

         // perform check on subscriber here
    }

请注意,我重构了您的代码,因为您应该避免嵌套订阅。

答案 1 :(得分:1)

在onSubscribe中创建一个新的Observable流通常是一个坏主意。

你应该考虑这样的事情:

    OneClass
    .doSth1(testString)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .doOnNext(testString2 -> manager.setTestString2(testString2))
    .flatMap(testString2 -> AnotherClass.doSth2(testString2))
    .doOnNext(testString3 -> manager.setTestString3(testString3))
    .map(setTestString3 -> true);

从我在您的代码中看到的内容,这应该可以为您提供所需内容。