IK.AM

@making's tech note


Reactor Testで鍛えるReactor脳トレ

🗃 {Programming/Java/reactor/core}
🏷 Reactor 🏷 Java 
🗓 Updated at 2017-10-11T09:24:40Z  🗓 Created at 2017-10-10T17:31:19Z   🌎 English Page

Reactorにはユニットテスト用のヘルパーStepVerifierが用意されています。

http://projectreactor.io/docs/core/release/reference/#testing

このStepVerifierを使うことで、テスト中に、Flux/Monosubscribeしたりblockしたりしなくても、 ストリームデータの内容を検証できるようになります。

依存ライブラリの追加

reactor-testを追加すれば利用可能です。

        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>

使い方

StepVerifier.createPublisherに渡して、expectXxxxメソッドで検証です。

以下は使用例です。

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<String> input = Flux.just("hoge", "foo", "bar");
        Flux<String> output = reactorDojo.identity(input);

        StepVerifier
                .create(output)
                .expectNext("hoge", "foo", "bar")
                .verifyComplete();
    }

    @Test
    public void toUppercase() throws Exception {
        Flux<String> input = Flux.just("hoge", "foo", "bar");
        Flux<String> output = reactorDojo.toUppercase(input);

        StepVerifier
                .create(output)
                .expectNext("HOGE", "FOO", "BAR")
                .verifyComplete();
    }

    @Test
    public void toOddNumbers() throws Exception {
        Flux<Integer> input = Flux.just(1, 2, 3, 4, 5, 6, 7, 8, 9);
        Flux<Integer> output = reactorDojo.oddNumbers(input);

        StepVerifier
                .create(output)
                .expectNext(1, 3, 5, 7, 9)
                .verifyComplete();
    }

    @Test
    public void commaSplit() throws Exception {
        Flux<String> input = Flux.just("aaa,bbb,", "ccc,ddddd,eee,", "ffff,g,", "hh,", "iiiii,jjj,");
        Flux<String> output = reactorDojo.commaSplit(input);

        StepVerifier
                .create(output)
                .expectNext("aaa", "bbb", "ccc", "ddddd", "eee", "ffff", "g", "hh", "iiiii", "jjj")
                .verifyComplete();
    }
}

Reactor脳トレ

では上記のテストをブラックボックステストとして、inputを受け取ってoutputを返すメソッドを実装してみてください。

次の雛形を利用してください。

import reactor.core.publisher.Flux;

import java.util.stream.Collectors;

public class ReactorDojo {

    public Flux<String> identity(Flux<String> input) {
        return input;
    }

    public Flux<String> toUppercase(Flux<String> input) {
        return input;
    }

    public Flux<Integer> oddNumbers(Flux<Integer> input) {
        return input;
    }

    public Flux<String> commaSplit(Flux<String> input) {
        return input;
    }
}

プロジェクトも用意しましたので、実装したい方は利用してください。

https://github.com/making/reactor-dojo

このままテストを実行すると3件のテストが失敗します。

image

全て緑になるように実装してみてください。簡単ですね?

真のReactor脳トレ

上記の例はとても簡単でJava 8のStream APIの利用経験があれば、実装できると思います。 では通常のStream APIでは実現できない例を挙げます。

上記のcommaSplitメソッドに対して次のテストケースも追加します。このテストも通るように実装してみてください。

    @Test
    public void commaSplitAdvanced() throws Exception {
        Flux<String> input = Flux.just("aaa,bb", "b,ccc,ddddd,e", "ee,ff", "ff,g,hh,i", "i", "iii,jjj,");
        Flux<String> output = reactorDojo.commaSplit(input);

        StepVerifier
                .create(output)
                .expectNext("aaa", "bbb", "ccc", "ddddd", "eee", "ffff", "g", "hh", "iiiii", "jjj")
                .verifyComplete();
    }

テストデータは有限なストリームですが、実際はデータが続くこと想定して実装してください。 次のテストケースでも成功しますか?

    @Test
    public void commaSplitAdvancedInfinite() throws Exception {
        Flux<String> input = Flux.just("aaa,bb", "b,ccc,ddddd,e", "ee,ff", "ff,g,hh,i", "i", "iii,jjj,").repeat();
        Flux<String> 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を送ってみてください。


✒️️ Edit  ⏰ History  🗑 Delete