--- title: Reactor Testで鍛えるReactor脳トレ tags: ["Reactor", "Java"] categories: ["Programming", "Java", "reactor", "core"] date: 2017-10-10T17:31:19Z updated: 2017-10-11T09:24:40Z --- Reactorにはユニットテスト用のヘルパー`StepVerifier`が用意されています。 http://projectreactor.io/docs/core/release/reference/#testing この`StepVerifier`を使うことで、テスト中に、`Flux`/`Mono`を`subscribe`したり`block`したりしなくても、 ストリームデータの内容を検証できるようになります。 ### 依存ライブラリの追加 `reactor-test`を追加すれば利用可能です。 ```xml io.projectreactor reactor-test test ``` ### 使い方 `StepVerifier.create`に`Publisher`に渡して、`expectXxxx`メソッドで検証です。 以下は使用例です。 ```java import org.junit.Test; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; public class ReactorDojoTest { ReactorDojo reactorDojo = new ReactorDojo(); @Test public void identity() throws Exception { Flux input = Flux.just("hoge", "foo", "bar"); Flux output = reactorDojo.identity(input); StepVerifier .create(output) .expectNext("hoge", "foo", "bar") .verifyComplete(); } @Test public void toUppercase() throws Exception { Flux input = Flux.just("hoge", "foo", "bar"); Flux output = reactorDojo.toUppercase(input); StepVerifier .create(output) .expectNext("HOGE", "FOO", "BAR") .verifyComplete(); } @Test public void toOddNumbers() throws Exception { Flux input = Flux.just(1, 2, 3, 4, 5, 6, 7, 8, 9); Flux output = reactorDojo.oddNumbers(input); StepVerifier .create(output) .expectNext(1, 3, 5, 7, 9) .verifyComplete(); } @Test public void commaSplit() throws Exception { Flux input = Flux.just("aaa,bbb,", "ccc,ddddd,eee,", "ffff,g,", "hh,", "iiiii,jjj,"); Flux output = reactorDojo.commaSplit(input); StepVerifier .create(output) .expectNext("aaa", "bbb", "ccc", "ddddd", "eee", "ffff", "g", "hh", "iiiii", "jjj") .verifyComplete(); } } ``` ### Reactor脳トレ では上記のテストをブラックボックステストとして、`input`を受け取って`output`を返すメソッドを実装してみてください。 次の雛形を利用してください。 ```java import reactor.core.publisher.Flux; import java.util.stream.Collectors; public class ReactorDojo { public Flux identity(Flux input) { return input; } public Flux toUppercase(Flux input) { return input; } public Flux oddNumbers(Flux input) { return input; } public Flux commaSplit(Flux input) { return input; } } ``` プロジェクトも用意しましたので、実装したい方は利用してください。 https://github.com/making/reactor-dojo このままテストを実行すると3件のテストが失敗します。 ![image](https://user-images.githubusercontent.com/106908/31400320-1cd4fdc2-ae2a-11e7-907c-f2773771fd16.png) 全て緑になるように実装してみてください。簡単ですね? ### 真のReactor脳トレ 上記の例はとても簡単でJava 8のStream APIの利用経験があれば、実装できると思います。 では通常のStream APIでは実現できない例を挙げます。 上記の`commaSplit`メソッドに対して次のテストケースも追加します。このテストも通るように実装してみてください。 ``` java @Test public void commaSplitAdvanced() throws Exception { Flux input = Flux.just("aaa,bb", "b,ccc,ddddd,e", "ee,ff", "ff,g,hh,i", "i", "iii,jjj,"); Flux output = reactorDojo.commaSplit(input); StepVerifier .create(output) .expectNext("aaa", "bbb", "ccc", "ddddd", "eee", "ffff", "g", "hh", "iiiii", "jjj") .verifyComplete(); } ``` テストデータは有限なストリームですが、実際はデータが続くこと想定して実装してください。 次のテストケースでも成功しますか? ```java @Test public void commaSplitAdvancedInfinite() throws Exception { Flux input = Flux.just("aaa,bb", "b,ccc,ddddd,e", "ee,ff", "ff,g,hh,i", "i", "iii,jjj,").repeat(); Flux output = reactorDojo.commaSplit(input); StepVerifier .create(output) .expectNext("aaa", "bbb", "ccc", "ddddd", "eee", "ffff", "g", "hh", "iiiii", "jjj") .expectNext("aaa", "bbb", "ccc", "ddddd", "eee", "ffff", "g", "hh", "iiiii", "jjj") .expectNext("aaa", "bbb", "ccc", "ddddd", "eee", "ffff", "g", "hh", "iiiii", "jjj"); } ``` これはちょっと難しいかも。考えてみてください。 できた方は[Pull Request](https://github.com/making/reactor-dojo/pulls)を送ってみてください。