似非プログラマのうんちく

「似非プログラマの覚え書き」出張版

JUnit 5 でテストコードがだいぶ変わったという話

JUnit 5 がとっくの昔にリリースされてたのを今頃になって確認してみたらいろいろ変わってた話。

アプリケーションコード

すごーい(CV : 尾崎由香)簡単な例でスマソ。

package jp.mydns.akanekodou;

/**
 * <p>文字列から整数への変換メソッド提供クラス</p>
 *
 * @version 1.1.1
 * @author akaneko3
 */
public class ParseNum {
    /**
     * <p>数値文字列を整数に変換する。</p>
     *
     * @param str 整数を表す文字列
     * @return 変換された整数値
     * @see Integer#parseInt(String)
     */
    public int parseNum(String str) {
        try {
            return Integer.parseInt(str);
        } catch (NumberFormatException nfe) {
            // NumberFormatException を catch したら
            // メッセージつきの NumberFormatException を throw する
            throw new NumberFormatException("入力された値が整数値を表していません。");
        }
    }
}
package jp.mydns.akanekodou;

import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;

/**
 * <p>
 * メインクラス<br />
 * 標準入力から取り込んだ文字列を整数値に変換する。
 * </p>
 *
 * @version 1.1
 * @author akaneko3
 */
public final class App {
    /**
     * <p>
     * private コンストラクタ<br />
     * (このクラスはインスタンスを生成しない)
     * </p>
     */
	private App() {}

    /**
     * <p>メインメソッド</p>
     *
     * @param args コマンドライン引数
     */
	public static void main(String[] args) {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            System.out.print("整数を入力してください: ");
            String str = br.readLine();
            ParseNum cn = new ParseNum();
            int value = cn.parseNum(str);
            System.out.println(value);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

テストコード

package jp.mydns.akanekodou;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
 * <p>JUnit5 による ChangeNum テスト用クラス</p>
 *
 * @author akaneko3
 */
public class ParseNumTest {
    /** テスト対象クラス */
    private static ParseNum target;

    /**
     * <p>
     * テスト前処理(全体を通して 1 回だけ実行)<br />
     * テスト対象クラスを生成する。
     * </p>
     */
    @BeforeAll
    public static void getTestClass() {
        target = new ParseNum();
    }

    /**
     * <p>{@link jp.mydns.akanekodou.ParseNum#parseNum(String)} の正常系テスト</p>
     */
    @Test
    public void success() {
        String str = "100";
        int expected = 100;
        int actual = target.parseNum(str);
        assertEquals(actual, expected);
    }

    /**
     * <p>{@link jp.mydns.akanekodou.ParseNum#parseNum(String)} の異常系テスト</p>
     */
    @Test
    public void exception() {
        String str = "99.9"; // 整数を表していない !
        Throwable exception = assertThrows(
            NumberFormatException.class,
            () -> target.parseNum(str)
        );
        assertEquals(exception.getMessage(), "入力された値が整数値を表していません。");
    }
}

ざっくりと変わったのが

  • @BeforeClass@BeforeAll
  • assertThat は消えた(同時に hamcrest も不必要に)ので各種 assert メソッドを使う
  • @Rule も消えた

ほんで、今まで独自ルール使って検証してた例外 throw 時のメッセージの検証は assertThrows の返り値から getMessage() で拾ってくることができるのがわかった。

余談 : jupiter は「木星が太陽系の 5 番目の惑星だから」ということにちなんでるらしい。