はじめに
最近のAndroidアプリ開発ではClean Architectureなど、設計の議論がすすみ、テストコードのためのツール群も増えたことで、テストコードを書くコストが減ってきているように感じます。
また、もう一つの流行としてRxJavaの採用事例が増えてきたように感じます。
JavaのJUnitテストやAndroidのテストにおいて、RxJavaのテストコードをどのように書くべきか、調べたことを書いていきたいと思います。
TestSubscriberについて
Subscriptionは非同期処理なので、ユニットテストするには同期処理が必要になります。(非同期処理のままにしておくと、Observableから値が返ってくる前にテストが終了してしまいます。)
公式のテスト方法はTestSubscriberクラスを利用することです。これはRxJavaライブラリに含まれています。
正常系のテスト
以下がコードのサンプルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
TestSubscriber#awaitTerminalEventはObservableSubscriberのonCompletedまたはonErrorを呼ぶまでブロックしてくれます。longとTimeUnitを引数に指定することで、タイムアウトも指定することができます
異常系のテスト
例外の発生をテストする場合は以下のようにかけます。
1 2 3 4 5 6 7 8 |
|
TestSubscriber#assertErrorでは引数に例外クラスまたはインスタンスを指定することで発生を検証できます。
ストリームとSubscriberの状態のテスト
Testsubscriber#assertValueはストリームの一番最後の値しか検証できません。1つの値しか返さない場合はこれでも良いのですが、複数の値が流れてくる場合は工夫する必要があります。
以下のコードでは説明を簡単にするためにTestSubscriberを直接操作しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
TestSubscriber#getOnNextEventsはonNextで受け取った値を全て保持しています。これを利用すると特定の場所に特定の値が流れてくることを検証できます。
またTestsubscriber#assertReceivedOnNextでonNextで受け取った値をリストで比較して検証できます。
Testsubscriber#assertValueCountはonNextで受け取った値の数を検証できます。
TestSubscriber#assertNotCompletedはonCompletedが呼ばれていないこと、
Testsubscriber#assertNoTerminalEventはそれに加えてonErrorも呼ばれていないことを検証できます。
Testsubscriber#assertUnsubscribedはunsubscribeされていることを検証できます。
おわりに
RxJavaにはテスト用のTestSubscriberクラスが準備されています。
RxJavaではObservable#flatMapによって個々のObservableを簡単に連結できるので、小さい単位でObservableを作成するコードを作成し、それぞれの入出力のテストコードを書いておくことで、堅牢で柔軟なモジュールが作成できるのではと思いました。
Gist
https://gist.github.com/fly1tkg/3c29dc34682b64076058
参考
http://reactivex.io/RxJava/javadoc/rx/observers/TestSubscriber.html