【Junit5】【ParameterizedTest】 2つ以上のパラメータをテストしたい場合

目次

はじめに

お世話になります、hosochinです
今回はJunit5のParameterizedTestの機能を使ってみたいと思います
こいつはJunit5から使えるアノテーションで、用意されたパラメータの分だけテストメソッドを実行してくれる便利機能です
テストメソッドがだいぶスッキリかけそうです
詳細については公式ドキュメントを参照してください

シンプルなParameterizedTest

こちらの記事にまとめています

2つ以上のパラメータをテストしたい場合

シンプルなパターンで紹介した@ValueSourceだと、1度に複数のパラメータを渡すことができません
複数パラメータを渡す手段として以下のようなアノテーションが用意されています

MethodSource

テストコード

    // テストメソッド
    @ParameterizedTest
    @MethodSource("methodSource")
    public void test(int param1, int param2, int expected) {
        assertEquals(expected, multiply(param1, param2));
    }

    // パラメータのファクトリメソッド
    public static Stream<Arguments> methodSource() {
        return Stream.of(
                arguments(10, 2, 20),
                arguments(10, 3, 30)
        );
    }

    // テスト対象のメソッド
    public int multiply(int param1, int param2) {
        return param1 * param2;
    }

説明

MethodSourceを使う場合はまずパラメータを生成するstaticメソッドを定義します(テストコードでいうmethodSourceメソッド)
このstaticメソッドはパラメータ群のStreamを返す必要があります
テストメソッドにはMethodSourceアノテーションを付与し、定義したstaticメソッドのメソッド名を指定してやります
パラメータ(と期待する結果)を直感的に分かりやすく記述できますね

CsvSource

テストコード

    // テストメソッド
    @ParameterizedTest
    @CsvSource({
            "10, 2, 20",
            "10, 3, 30"})
    public void test(int param1, int param2, int expected) {
        assertEquals(expected, multiply(param1, param2));
    }

説明

MethodSourceの例で挙げたテストコードをCsvSourceを使って書いてみました
MethodSourceだとstaticメソッドを書く必要があったので、CsvSourceならより簡潔に書けそうです
パラメータは文字列で記述する必要があり、これらは暗黙の型変換によってキャストされます
変換ルールについてはこちらを参照
まあこいつが便利なんですけど、初見だと分かりづらいかなと思ったり思わなかったり

EnumSource

テストコード

    @ParameterizedTest
    @EnumSource(names = { "DAYS", "HOURS" })
    void test(ChronoUnit unit) {
        // ...省略
    }

説明

EnumSourceはパラメータにenumを使用することができます
利用するにはEnumSourceアノテーションを付与してあげます
オプションのnamesでenumの要素を指定できます(namesを省略した場合、全ての要素を指定した扱いになります)
あと、パラメータのパターンをenumで定義してやればMethodSourceみたいなこともできます

    @ParameterizedTest
    @EnumSource
    public void test(ParamEnum paramEnum) {
        assertEquals(paramEnum.expected, multiply(paramEnum.param1, paramEnum.param2));
    }

    @RequiredArgsConstructor
    enum ParamEnum {
        TEST1(10, 2, 20),
        TEST2(10, 3, 30);

        private final int param1;
        private final int param2;
        private final int expected;
    }

個人的には単純なパターンのテストであれば、MethodSource使うより見やすいかなと思いました😎

技術Java,junit

Posted by hosochin