サーチ…


備考

Schedulerメソッドはすべて静的なので、RxJavaフックを利用した単体テストを同じJVMインスタンス上で並列に実行することはできません。それらがどこにあれば、ユニットテストの途中で1つのTestSchedulerが削除されます。基本的にはSchedulersクラスを使用することの欠点です。

TestSubscriber

TestSubscribersを使用すると、独自のサブスクライバを作成したり、アクションをサブスクライブする作業を避けることができます。特定の値が配信されているかどうか、Observableが完了したかどうか、例外が発生したかどうか、

入門

この例では、値1,2,3および4がonNext経由でObservableに渡されたというアサーションを示しています。

TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
ts.assertValues(1,2,3,4); // Success

assertValuesは、カウントが正しいことをアサートします。いくつかの値を渡すだけなら、アサーションは失敗します。

TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
ts.assertValues(1,2,3); // Fail

assertValuesは、アサート時にequalsメソッドを使用します。これにより、データとして扱われるクラスを簡単にテストできます。

TestSubscriber<Object> ts = TestSubscriber.create();
Observable.just(new Object(), new Object()).subscribe(ts);
ts.assertValues(new Object(), new Object()); // Fail

この例では、equalsが定義され、Observableの値をアサートするクラスを示します。

public class Room {

    public String floor;
    public String number;

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (o instanceof Room) {
            Room that = (Room) o;
            return (this.floor.equals(that.floor))
                    && (this.number.equals(that.number));
        }
        return false;
    }
}

TestSubscriber<Room> ts = TestSubscriber.create();
Observable.just(new Room("1", "10")).subscribe(ts);
ts.assertValue(new Room("1", "10"); // Success

また、1つの項目をチェックするだけでよいので、より短いassertValueを使用することに注意してください。

すべてのイベントを取得する

必要があれば、すべてのイベントをリストとして尋ねることもできます。

TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
List<Integer> onNextEvents = ts.getOnNextEvents();
List<Throwable> onErrorEvents = ts.getOnErrorEvents();
List<Notification<Integer>> onCompletedEvents = ts.getOnCompletedEvents();

イベントのアサート

あなたのイベントについてより広範なテストをしたい場合は、あなたの好きなアサーションライブラリとgetOnNextEvents (またはgetOn*Events )を組み合わせることができます:

Observable<Integer> obs = Observable.just(1,2,3,4)
    .filter( x -> x % 2 == 0);

// note that we instanciate TestSubscriber via the constructor here 
TestSubscriber<Integer> ts = new TestSubscriber();
obs.subscribe(ts);

// Note that we are not using Observable#forEach here
// but java.lang.Iterable#forEach.
// You should never use Observable#forEach unless you know
// exactly what you're doing
ts.getOnNextEvents()
    .forEach( integer -> assertTrue(integer % 2 == 0));

検査Observable#errorテストする

正しい例外クラスが生成されていることを確認することができます:

Observable<Integer> obs = Observable.error(new Exception("I am a Teapot"));

TestSubscriber<Integer> ts = new TestSubscriber<>();
obs.subscribe(ts);

ts.assertError(Exception.class);

また、正確な例外がスローされたことを確認することもできます。

Exception e = new Exception("I am a Teapot");
Observable<Integer> obs = Observable.error(e);

TestSubscriber<Integer> ts = new TestSubscriber<>();
obs.subscribe(ts);

ts.assertError(e);

TestScheduler

TestSchedulersを使用すると、ビジーな待ち時間やスレッド結合など、システム時間を操作する必要がなく、オブザーバブルの時間と実行を制御できます。これは、予測可能で一貫性のある高速な単体テストを作成したい場合には非常に重要です。あなたが時間を操作しているので、スレッドが枯渇したり、テストが遅いマシンで失敗したり、結果を待っている実行時間を浪費したりする可能性はなくなりました。

TestSchedulersは、RxJava操作のためにスケジューラを必要とするオーバーロードを介して提供することができます。

TestScheduler testScheduler = new TestScheduler();
TestSubscriber<Integer> subscriber = TestSubscriber.create();
Observable.just(1,2,3)
          .delay(10, TimeUnit.SECONDS, testScheduler)
          .subscribe(subscriber);

try {
    Thread.sleep(TimeUnit.SECONDS.toMillis(11));
} catch (InterruptedException ignored) { }
subscriber.assertValues(1,2,3); // fails

testScheduler.advanceTimeBy(10, TimeUnit.SECONDS);
subscriber.assertValues(1,2,3); // success

TestSchedulerはかなり基本的です。これは3つの方法で構成されています。

testScheduler.advanceTimeBy(amount, timeUnit);
testScheduler.advanceTimeTo(when, timeUnit);
testScheduler.triggerActions();

これにより、TestSchedulerが将来のある時点のすべてのアクションを起動する必要があるときに操作できます。

スケジューラーを通過する間、これはどのように効果的でないかのためにTestSchedulerが一般的に使用される方法ではありません。スケジューラをクラスに渡すことで、少しでも多くの余分なコードを提供することになります。代わりに、RxJavaのSchedulers.io()/ computed()/ etcにフックできます。これはRxJavaのフックで行われます。これにより、Schedulerメソッドの1つからコールから返される内容を定義できます。

public final class TestSchedulers {

    public static TestScheduler test() {
        final TestScheduler testScheduler = new TestScheduler();
        RxJavaHooks.reset();
        RxJavaHooks.setOnComputationScheduler((scheduler) -> {
            return testScheduler;
        });
        RxJavaHooks.setOnIOScheduler((scheduler) -> {
            return testScheduler;
        });
        RxJavaHooks.setOnNewThreadScheduler((scheduler) -> {
            return testScheduler;
        });
        return testScheduler;
    }
}

このクラスを使用すると、スケジューラへのすべてのコールに接続されるテストスケジューラを取得できます。単体テストでは、このスケジューラをセットアップするだけでよいでしょう。 TestSchedulerはあなたが時間を進めるときに別の単体テストからtriggerActionsを試みるかもしれないので、セットアップでそれを取得することを強くお勧めします。上の例は

TestScheduler testScheduler = new TestScheduler();
TestSubscriber<Integer> subscriber = TestSubscriber.create();
Observable.just(1,2,3)
          .delay(10, TimeUnit.SECONDS, testScheduler)
          .subscribe(subscriber);
testScheduler.advanceTimeBy(9, TimeUnit.SECONDS);
subscriber.assertValues(); // success (delay hasn't finished)
testScheduler.advanceTimeBy(10, TimeUnit.SECONDS);
subscriber.assertValues(1,2,3); // success (delay has finished)

これはあなたがユニットテストからシステムクロックを効果的に取り除く方法です(少なくともRxJavaに関すること😆)



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow