2016-09-07 3 views
0

私のアンドロイドプロジェクトでRxJavaを使用しています。実際に私のコードをテストしています。複雑なRxJavaオブザーバブルをテストするには

私は

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(文字列た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(オブジェクト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

代わりに直接スケジューラを使用して、あなたはそれを注入し、代わりにTestSchedulerを使用することもできます。それはあなたがコントロールの実行を許可します。 (ユニットテスト用として、他のスケジューラに対処するために複雑になる場合があります)

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

は、その後、あなたのテストでは、あなたの代わりに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 
    } 

ネストされたサブスクリプションを避けるようにコードをリファクタリングしました。

+0

このソリューションでは、プロジェクト全体をたくさん変更する必要があります。私はメソッド "changeMyString()"を呼び出す静的メソッドを持つprivateコンストラクタを使用しています – NullPointer

+0

あなたのプロジェクトはモジュール化されておらず、変更が容易ではありません。 RxPluginsを使用してスケジューラを注入することはできますが、テストすることはお勧めしません。 – dwursteisen

+0

私の質問を編集しました。これで、私の他のメソッド呼び出しが何をしているかを見ることができます。そうでなければ私を助けることができますか? – NullPointer

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

私はあなたのコードで表示されるものとし、これが何をしたいあなたを与える必要があります。

+0

これは動作しません。それは "AnotherClass.doSth2(testString2)"メソッドを呼び出すことはありません...私は本当に私が間違っているか分からない – NullPointer

+0

ホー、それじゃない? OneClass.doSth1(...)が少なくとも1つのアイテムを放出していますか? これらのメソッドが何をしているかを教えてください。 – cambierr

+0

私は自分の質問を編集して、メソッドが何をしているのかを見ています – NullPointer

関連する問題