Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

JavaでPrivateメソッドのUnitTestを行う

  • 概要

好みの世界ではあるが、クラス内でメソッドの内容を細かく
Privateメソッドに分割する人向けの内容。
DRY原則を守る意味でも小分けにするほうが好みです。

  • サンプルコード前提条件

テストされるクラスはPrivateMethodSample。
テスト用の例外クラスをPrivateMethodException。
テスト用の個人情報クラスをPersonalInfo。
テストクラスをPrivateMethodTestとします。

  • サンプルコード

テスト対象のクラス(PrivateMethodSample)

public class PrivateMethodSample {
	/**
	 * 個人情報.
	 */
	PersonalInfo person;

	/**
	 * PrivateMethodTesteeのコンストラクタ.
	 *
	 * <pre>
	 * 個人情報を初期設定
	 * </pre>
	 *
	 * @param person
	 *            個人情報
	 */
	public PrivateMethodSample(PersonalInfo person) {
		this.person = person;
	}

	/**
	 * checkPersonalInfoのパラメータチェック
	 *
	 * <pre>
	 * 個人情報の内容確認
	 * </pre>
	 */
	public void checkPersonalInfo() throws PrivateMethodException {
		checkFirstName();
		checkFamilyName();
	}

	/**
	 * 名の内容確認.
	 *
	 * <pre>
	 * 名前が空文字もしくはnullでないことを確認する
	 * </pre>
	 */
	private void checkFirstName() throws PrivateMethodException {
		if (isNullString(this.person.getFirstName())) {
			throw new PrivateMethodException("名が誤っています");
		}
	}

	/**
	 * 姓の内容確認.
	 *
	 * <pre>
	 * 苗字が空文字もしくはnullでないことを確認する
	 * </pre>
	 */
	private void checkFamilyName() throws PrivateMethodException {
		if (isNullString(this.person.getFamilyName())) {
			throw new PrivateMethodException("姓が誤っています");
		}
	}

	/**
	 * 対象文字列がnullもしくは空文字列か判断する.
	 *
	 * @param target
	 *            対象文字列
	 * @return true=空もしくは、nullの場合,false=空もしくは、nullではない場合
	 */
	private boolean isNullString(String target) {
		if (target == null || target.length() == 0) {
			return true;
		}
		return false;
	}

}

テスト用例外クラス(PrivateMethodException)

public class PrivateMethodException extends Exception {

	private static final long serialVersionUID = 1L;

	public PrivateMethodException(String message) {
		super(message);

	}

}

テスト用個人情報クラス(PersonalInfo)

public class PersonalInfo {
	public String firstName;
	public String getFirstName() {
		return firstName;
	}

	public String getFamilyName() {
		return familyName;
	}

	public String familyName;

	public PersonalInfo(String firstName, String familyName) {
		this.firstName = firstName;
		this.familyName = familyName;
	}
}

テストクラス(PrivateMethodTest)

public class PrivateMethodSampleTest extends DJUnitTestCase {
	:
	// 他のテスト内容は省略

	/**
	 * null空文字チェックテスト_空文字の場合.
	 */
	@Test
	public void testIsNullString_空文字() throws NoSuchMethodException,InvocationTargetException,IllegalAccessException {
		PersonalInfo person = new PersonalInfo("一郎", "田中");
		PrivateMethodSample privateMethod = new PrivateMethodSample(person);
		Class<PrivateMethodSample> clazz = PrivateMethodSample.class;
		Method method = clazz.getDeclaredMethod( "isNullString" ,String.class );
		method.setAccessible( true );
		boolean ret = (Boolean)method.invoke(privateMethod, "");
		assertEquals(true, ret);
	}

	/**
	 * null空文字チェックテスト_nullの場合.
	 */
	@Test
	public void testIsNullString_null() throws NoSuchMethodException,InvocationTargetException,IllegalAccessException {
		PersonalInfo person = new PersonalInfo("一郎", "田中");
		PrivateMethodSample privateMethod = new PrivateMethodSample(person);
		Class<PrivateMethodSample> clazz = PrivateMethodSample.class;
		Method method = clazz.getDeclaredMethod( "isNullString" ,String.class );
		method.setAccessible( true );
		boolean ret = (Boolean)method.invoke(privateMethod, "");
		assertEquals(true, ret);
	}

	/**
	 * null空文字チェックテスト_「テスト」という文字列の場合.
	 */
	@Test
	public void testIsNullString_テスト文字列() throws NoSuchMethodException,InvocationTargetException,IllegalAccessException {
		PersonalInfo person = new PersonalInfo("一郎", "田中");
		PrivateMethodSample privateMethod = new PrivateMethodSample(person);
		Class<PrivateMethodSample> clazz = PrivateMethodSample.class;
		Method method = clazz.getDeclaredMethod( "isNullString" ,String.class );
		method.setAccessible( true );
		boolean ret = (Boolean)method.invoke(privateMethod, "テスト");
		assertEquals(false, ret);
	}
}
  • 説明

PrivateMethodSampleは初期化時に個人情報を保持します。
checkPersonalInfoメソッドで個人情報の内容が正しい確認します。

その際に、設定内容が空文字かnull判定を行うのですが
姓名の2箇所で利用するためこの処理をprivateメソッドに分割しました。
このprivateメソッド自体の機能をテストする場合、
リフレクションを利用することで対応可能です。

以下の部分ですね。

		Class<PrivateMethodSample> clazz = PrivateMethodSample.class;
		Method method = clazz.getDeclaredMethod( "isNullString" ,String.class );
		method.setAccessible( true );
		boolean ret = (Boolean)method.invoke(privateMethod, "テスト");

メソッドインスタンスを取得し、setAccessible( true )で無理やりアクセス可能にしています。
この際に、テストメソッドないだけの対応で実態のコードを修正することなく
アクセス出来るのがポイント。

上記のコードで無事Privateメソッドのテストに成功。