privateメソッドの場合も、staticメソッドの場合と同様に、PowerMockを利用してMock化することができる。今回は、privateメソッドのMock化と呼出確認を行ってみたので、そのサンプルプログラムを共有する。
前提条件
下記記事の実装が完了していること。
サンプルプログラムの内容
作成したサンプルプログラムの構成は以下の通り。
なお、上記の赤枠のうち、「DateCheckUtil.java」がテスト対象のプログラムで、「DateCheckUtilTest.java」が今回新規で作成したプログラムとなる。
DateCheckUtil.javaの内容は以下の通り。そのうち、今回のテストプログラムに関連するのは「checkDate」「isCorrectDate」メソッドとなる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | package com.example.demo; import java.time.LocalDate; import java.time.chrono.JapaneseChronology; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; import java.util.Locale; public class DateCheckUtil { /** * 日付チェック処理を行う * @param year 年 * @param month 月 * @param day 日 * @return 判定結果(1:年が空、2:月が空、3:日が空、4:年月日が不正、5:年月日が未来日、0:正常 */ public static int checkDate(String year, String month, String day){ final String dateFormat = "uuuuMMdd"; if(isEmpty(year)){ return 1; } if(isEmpty(month)){ return 2; } if(isEmpty(day)){ return 3; } String dateStr = year + addZero(month) + addZero(day); if(!isCorrectDate(dateStr, dateFormat)){ return 4; } if(isFutureDate(dateStr, dateFormat)){ return 5; } return 0; } /** * DateTimeFormatterを利用して日付チェックを行う * @param dateStr チェック対象文字列 * @param dateFormat 日付フォーマット * @return 日付チェック結果 */ private static boolean isCorrectDate(String dateStr, String dateFormat){ if(isEmpty(dateStr) || isEmpty(dateFormat)){ return false; } //日付と時刻を厳密に解決するスタイルで、DateTimeFormatterオブジェクトを作成 DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat) .withResolverStyle(ResolverStyle.STRICT); try{ //チェック対象文字列をLocalDate型の日付に変換できれば、チェックOKとする LocalDate.parse(dateStr, df); return true; }catch(Exception e){ return false; } } /** * 日付の文字列が未来日かどうかを判定する * @param dateStr チェック対象文字列 * @param dateFormat 日付フォーマット * @return 判定結果 */ private static boolean isFutureDate(String dateStr, String dateFormat){ if(!isCorrectDate(dateStr, dateFormat)){ return false; } LocalDate dateStrDate = convertStrToLocalDate(dateStr, dateFormat); LocalDate now = LocalDate.now(); if(dateStrDate.isAfter(now)){ return true; } return false; } /** * 日付の文字列を日付型に変換した結果を返す * @param dateStr 日付の文字列 * @param dateFormat 日付のフォーマット * @return 変換後の文字列 */ private static LocalDate convertStrToLocalDate(String dateStr, String dateFormat){ if(isEmpty(dateStr) || isEmpty(dateFormat)){ return null; } //日付と時刻を厳密に解決するスタイルで、暦体系は和暦体系で、 //DateTimeFormatterオブジェクトを作成 DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat, Locale.JAPAN) .withChronology(JapaneseChronology.INSTANCE) .withResolverStyle(ResolverStyle.STRICT); //日付の文字列をLocalDate型に変換して返却 return LocalDate.parse(dateStr, df); } /** * 数値文字列が1桁の場合、頭に0を付けて返す * @param intNum 数値文字列 * @return 変換後数値文字列 */ private static String addZero(String intNum){ if(isEmpty(intNum)){ return intNum; } if(intNum.length() == 1){ return "0" + intNum; } return intNum; } /** * 引数の文字列がnull、空文字かどうかを判定する * @param str チェック対象文字列 * @return 文字列チェック結果 */ public static boolean isEmpty(String str){ if(str == null || "".equals(str)){ return true; } return false; } } |
また、DateCheckUtilTest.javaの内容は以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | package com.example.demo; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import static org.junit.Assert.assertEquals; @RunWith(PowerMockRunner.class) @PrepareForTest({DateCheckUtil.class}) public class DateCheckUtilTest { /** * 前処理(各テストケースを実行する前に行われる処理) */ @Before public void init(){ //DateCheckUtilクラスをSpyで一部をMock設定 PowerMockito.spy(DateCheckUtil.class); } /** * DateCheckUtilクラスのcheckDateメソッドの確認 * (DateCheckUtil.isCorrectDateをMock設定した場合の確認) */ @Test public void testDateCheckUtilCheckDateMock() throws Exception{ //privateメソッドであるDateCheckUtil.isCorrectDateを呼び出したときに、 //falseを返却するようMock設定 PowerMockito.doReturn(false) .when(DateCheckUtil.class, "isCorrectDate" , Mockito.any(), Mockito.any()); //DateCheckUtil.checkDateを呼び出し、戻り値を確認 //checkDateメソッドの引数に正しい年月日を指定しているが、 //isCorrectDateメソッドでfalseを返すようにMock設定したため、 //DateCheckUtil.checkDateメソッドの戻り値が4になる int retVal = DateCheckUtil.checkDate("2012", "12", "27"); assertEquals(4, retVal); } /** * DateCheckUtilクラスのcheckDateメソッドの確認 * (DateCheckUtil.isCorrectDateの呼出回数と引数の確認) */ @Test public void testDateCheckUtilCheckDateVerify() throws Exception{ //DateCheckUtil.checkDateを呼び出し、戻り値を確認 int retVal = DateCheckUtil.checkDate("2012", "12", "32"); assertEquals(4, retVal); //DateCheckUtil.isCorrectDateメソッドの呼出回数が1回であることを確認し、 //その際の引数も取得 ArgumentCaptor<String> dateStrArg = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> dateFormatArg = ArgumentCaptor.forClass(String.class); PowerMockito.verifyPrivate(DateCheckUtil.class, Mockito.times(1)) .invoke("isCorrectDate", dateStrArg.capture(), dateFormatArg.capture()); //DateCheckUtil.isCorrectDateメソッドの引数を確認 assertEquals("20121232", dateStrArg.getValue()); assertEquals("uuuuMMdd", dateFormatArg.getValue()); } } |
上記プログラムのtestDateCheckUtilCheckDateMockメソッドでは、DateCheckUtil.javaのprivateメソッド「isCorrectDate」をMock化している。PowerMockitoのwhen句で、staticメソッドの場合と同じように、第一引数にstaticメソッドを含むクラス名.classを、第二引数にメソッド名を、第三引数以降にメソッドの引数(任意値はMockito.any()で指定)を指定している。
また、testDateCheckUtilCheckDateVerifyメソッドでは、DateCheckUtil.javaのprivateメソッド「isCorrectDate」の呼出回数と引数を取得している。PowerMockito.verifyPrivateメソッドを利用し、呼出回数はMockito.times句で確認し、invokeメソッド内でメソッド名と引数の指定を行っている。さらに、staticメソッドの場合と同様に、そのメソッド呼出時の引数は、ArgumentCaptorクラスを利用することで取得できる。
その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/junit-powermock-private/demo
今回作成した「DateCheckUtilTest.java」の実行結果は以下の通り。
要点まとめ
- privateメソッドの場合も、PowerMockを利用することで、Mock化や呼出回数・引数の確認が行える。