0

I am using RxJava in my android project and I'm actually starting unit testing my code.

I have following Observable method which I'm going to test

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

My Test case looks like the following:

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

When I debug my Code it's not reaching this part here:

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

How can I write a Unit test for this case? I can't figure it out, why it's not working...

Thanks for your help guys!

Alban

Charles Mager
  • 25,735
  • 2
  • 35
  • 45
NullPointer
  • 1,250
  • 2
  • 12
  • 17

2 Answers2

2

Instead of using directly Schedulers, you may want to inject it and use TestScheduler instead. It will allow your to controle executions. (as for an unit test, it may be complicated to deal with others schedulers)

For more information on the TestScheduler : How 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));
         }
 }

Then in your test, you can inject a TestScheduler instead :

   @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
    }

Please note that I refactored your code as you should avoid nested subscription.

Community
  • 1
  • 1
dwursteisen
  • 11,435
  • 2
  • 39
  • 36
  • For this solution I have to change a lot of my whole project. I am using private constructors with a static method which calls the method "changeMyString()" – NullPointer Sep 07 '16 at 12:24
  • So your project is not modular and won't be easy to change (for example for testing purpose !). You still can inject a scheduler using RxPlugins but it's not recommended for testing. – dwursteisen Sep 07 '16 at 12:29
  • I edited my question. Now you can see what my other method calls are doing. Maybe you can help me otherwise? – NullPointer Sep 07 '16 at 17:47
1

Creating a new Observable stream inside a onSubscribe is generally a bad idea.

You should consider something like this:

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

From what I see in your code, this should give you what you want.

cambierr
  • 391
  • 4
  • 14
  • This one is not working. It is not calling the "AnotherClass.doSth2(testString2)"-method.... I really don't know what I am doing wrong – NullPointer Sep 07 '16 at 12:13
  • Ho, isn't it ? are you sure OneClass.doSth1(...) is emitting at least one item ? Maybe you provide us with what those methods are doing ? – cambierr Sep 07 '16 at 12:59
  • I edited my question so you see what the methods are doing – NullPointer Sep 07 '16 at 13:47