ほげほげ(仮)

仮死状態

RxJavaのHotObservableのテストコード

HotObservableのテストコードを書く方法です。ちょっと調べたのですが、良い方法が見つからず自分なりに考えてみました。

もっと良い方法あったら教えてください。

環境

ごめんなさい、RxJava1です。RxJava2まだ追えてません。

対象コード

単純な足し算をして、それをHotObservableで通知するだけのものです。

これのテストコードを書きます。

public class Hoge {

    private final PublishSubject<Integer> subject = PublishSubject.create();
    public final Observable<Integer> observable = subject.asObservable();

    public void operation(int a, int b) {
        subject.onNext(a + b);
    }
}

TestSubscriber

RxJava関連のテストコードでよく使われると思いますが、TestSubscriberというのがあります。

これにawaitTerminalEventっていうメソッドがあって、onCompletedonErrorが呼ばれるまで待ちます。普通のColdなObservableとかはこれを使って処理が終わるのを待つことが可能ですが、HotなObservableの場合はonCompletedonErrorも呼ばれないので処理を待つことが難しいです。

awaitTerminalEventタイムアウトが設定できるので、とりあえずそれでお茶を濁すことも可能ですが、常にその時間待つことになります。

// 1秒でタイムアウト
// HotObservableの場合は毎回1秒待つ
testSubscriber.awaitTerminalEvent(1, TimeUnit.SECONDS);

なので、onNextが呼ばれたときにonCompletedを呼ぶように継承してHotObservable用のTestSubscriberを作ります。

ついでに呼ばれる回数も指定できるようにしてあります。

public class HotTestSubscriber<T> extends TestSubscriber<T> {

    private int count;

    public HotTestSubscriber(int count) {
        this.count = count;
    }

    @Override
    public void onNext(T t) {
        super.onNext(t);

        count--;

        // 指定回数呼ばれたらonCompletedを呼んで終了
        if (count == 0) {
            onCompleted();
        }
    }

    public static <T> HotTestSubscriber<T> create() {
        return new HotTestSubscriber<T>(1);
    }

    public static <T> HotTestSubscriber<T> create(int count) {
        return new HotTestSubscriber<T>(count);
    }
}

テストコード

先程の足し算のテストコードを書いてみます。

public class HogeTest {

    @Test
    public void operation() throws Exception {
        Hoge hoge = new Hoge();

        HotTestSubscriber<Integer> testSubscriber = HotTestSubscriber.create();
        hoge.observable.subscribe(testSubscriber);

        hoge.operation(1, 2);

        // 処理が終わるのを待つ(一応タイムアウトも設定しておく)
        testSubscriber.awaitTerminalEvent(1, TimeUnit.SECONDS);

        // onNextが呼ばれた回数を確認
        testSubscriber.assertValueCount(1);

        // onNextに入ってきた値を確認
        testSubscriber.assertValue(3);
    }
}

これでHotObservableもテストできるようになりました。