渡辺修司さん著の「JUnit実践入門」を読んで、写経して、コードが本に載っていなかったり、ダウンロードしたサンプルに入っていなかったりしたので、自分なりに考えて補足しました。
第一段
第20章 テストダブルの活用 20.1 システムに依存するテスト
リスト20.3に対するテストコードがないので、下記に記します。テスト対象コードのクラス名はMonthlyCalendar2とします。テストコードでは、MonthlyCalendar2を継承する無名クラスで、geCalendarメソッドをオーバーライドします。
package ch20.ex01; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.util.Calendar; import org.junit.Test; public class MonthlyCalendar2Test { @Test public void 現在時刻が20120131の場合getRemainingDaysは0を返す() throws Exception { MonthlyCalendar2 sut = new MonthlyCalendar2() { @Override Calendar getCalendar() { return newCalendar(2012, 1, 31); } }; assertThat(sut.getRemainingDays(), is(0)); } @Test public void 現在時刻が20120130の場合getRemainingDaysは1を返す() throws Exception { MonthlyCalendar2 sut = new MonthlyCalendar2() { @Override Calendar getCalendar() { return newCalendar(2012, 1, 30); } }; assertThat(sut.getRemainingDays(), is(1)); } @Test public void 現在時刻が20120201の場合getRemainingDaysは28を返す() throws Exception { MonthlyCalendar2 sut = new MonthlyCalendar2() { @Override Calendar getCalendar() { return newCalendar(2012, 2, 1); } }; assertThat(sut.getRemainingDays(), is(28)); } static Calendar newCalendar(int yyyy, int mm, int dd) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR, yyyy); cal.set(Calendar.MONTH, mm - 1); cal.set(Calendar.DATE, dd); cal.set(Calendar.HOUR, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal; } }
リスト20.4のテストコードを作って、テストをしようとしましたが、リスト20.4のコードだと、私はテストコードが書けませんでした。修正したテスト対象コードは次のようになりました。
テスト対象コード
package ch20.ex01; import java.util.Calendar; interface SystemCalendar { Calendar getInstance(); } public class MonthlyCalendar3 implements SystemCalendar { @Override public Calendar getInstance() { return Calendar.getInstance(); } }
そして、テストコードは、下記のようになりました。テストで制御できない処理を別のクラスに移譲するのですが、その移譲クラスでgetRemainingDaysメソッドを実装しました。
package ch20.ex01; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.util.Calendar; import org.junit.Test; public class MonthlyCalendar3Test { @Test public void 現在時刻が20120131の場合getRemainingDaysは0を返す() throws Exception { DelegateObjectExample sut = new DelegateObjectExample(); sut.setDate(2012, 1, 31); assertThat(sut.getRemainingDays(), is(0)); } @Test public void 現在時刻が20120130の場合getRemainingDaysは1を返す() throws Exception { DelegateObjectExample sut = new DelegateObjectExample(); sut.setDate(2012, 1, 30); assertThat(sut.getRemainingDays(), is(1)); } @Test public void 現在時刻が20120201の場合getRemainingDaysは28を返す() throws Exception { DelegateObjectExample sut = new DelegateObjectExample(); sut.setDate(2012, 2, 1); assertThat(sut.getRemainingDays(), is(28)); } } class DelegateObjectExample { SystemCalendar sysCal = new MonthlyCalendar3(); Calendar cal; public void setDate(int yyyy, int mm, int dd) { cal = sysCal.getInstance(); cal = newCalendar(yyyy, mm, dd); } public int getRemainingDays() { return cal.getActualMaximum(Calendar.DATE) - cal.get(Calendar.DATE); } static Calendar newCalendar(int yyyy, int mm, int dd) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR, yyyy); cal.set(Calendar.MONTH, mm - 1); cal.set(Calendar.DATE, dd); cal.set(Calendar.HOUR, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal; } }