読者です 読者をやめる 読者になる 読者になる

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

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

JUnit4 による例外発生時のメッセージのテスト

Java JUnit

JUnit 4.7 からの機能で、例外が throw されたときのメッセージ(getMessage で取得できる文字列)をチェックすることが出来るようになったらしい。具体的には、同じ例外クラスを throw するが、ケースによってメッセージが変わるような場合に、@Test(expected = ...) では確認しきれないので、この方法を使うようである。

実際例

前回の例を修正して、今回の実際例として用いる。

ChangeNum クラスの修正

package jp.mydns.akanekodou;

/**
 * <p>整数を表す文字列を整数に変換する</p>
 *
 * @version 1.1
 * @author Red cat
 */
public class ChangeNum {
    /**
     * <p>数値文字列を整数に変換する</p>
     *
     * @param str 整数を表す文字列
     * @return 変換された整数値
     * @throws NumberFormatException 引数の文字列が整数値を表していないとき
     * @see Integer#parseInt(String)
     */
    public int changeNum(String str) throws NumberFormatException {
        try {
            return Integer.parseInt(str);
        } catch(NumberFormatException e) {
            // NumberFormatException を catch したら
            // メッセージつきの NumberFormatException を throw する
            throw new NumberFormatException("入力された値が整数値を表していません。");
        }
    }
}

NumberFormatExceptioncatch した際に、エラーメッセージを独自に設定した NumberFormatException を新たに throw する仕様に変更している。

例外検証ルールの作成

@Rule アノテーションExpectedException クラスを利用して検証ルールを作成する。

package jp.mydns.akanekodou.test.junit4;

import jp.mydns.akanekodou.ChangeNum;

import org.junit.*;
import org.junit.rules.ExpectedException;

import static org.junit.Assert.*;
import static org.hamcrest.core.Is.is;

/**
 * <p>JUnit4 による ChangeNum テスト用クラス</p>
 *
 * @author Red cat
 */
public class ChangeNumTest {
    private static ChangeNum target;

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    /**
     * <p>
     * テスト前処理<br />
     * 全体を通して 1 回だけ実行
     * </p>
     */
    @BeforeClass
    public static void getTestClass() {
        target = new ChangeNum();
    }

    /**
     * <p>正常系テスト</p>
     */
    @Test
    public void success() {
        String str = "100";
        int expected = 100;
        int actual = target.changeNum(str);
        assertThat("数値に変換されていません。", actual, is(expected));
    }

    /**
     * <p>異常系テスト</p>
     */
    @Test
    public void exception() {
        String str = "99.9"; // 整数を表していない !
        // 例外検証ルールの設定
        thrown.expect(NumberFormatException.class);
        thrown.expectMessage("入力された値が整数値を表していません。");
        target.changeNum(str); // ここで NumberFormatException が発生するはず
    }
}

これで期待される例外のみならず、その際に期待されるエラーメッセージも一致したときに限って異常系のテストが成功する。

(参考)JUnit3 による例外発生時のメッセージテスト

JUnit3 の場合はことがもう少し簡単(?)で、一行追加するだけである。

package jp.mydns.akanekodou.test.junit3;

import jp.mydns.akanekodou.ChangeNum;

import junit.framework.*;

/**
 * <p>JUnit3 による ChangeNum テスト用クラス</p>
 *
 * @author Red cat
 */
public class ChangeNumTest extends TestCase {
    private ChangeNum target;

    /**
     * <p>コンストラクタ</p>
     *
     * @param name {@inheritDoc}
     * @see TestCase#TestCase(String)
     */
    public ChangeNumTest(String name) {
        super(name);
    }

    /**
     * <p>
     * テスト前処理<br />
     * 各テストメソッドの前に毎回実行
     * </p>
     *
     * @see TestCase#setUp()
     */
    @Override
    public void setUp() {
        target = new ChangeNum();
    }

    /**
     * <p>正常系テスト</p>
     */
    public void testSuccess() {
        String str = "100";
        int expected = 100;
        int actual = target.changeNum(str);
        assertEquals("数値に変換されていません。", expected, actual);
    }

    /**
     * <p>異常系テスト</p>
     */
    public void testException() {
        String str = "99.9"; // 整数を表していない !
        try {
            target.changeNum(str); // ここで NumberFormatException が発生するはず
            fail("例外が発生していません。");
        } catch(NumberFormatException e) {
            assertEquals("入力された値が整数値を表していません。", e.getMessage());
        }
    }
}