渡辺修司さん著の「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;
}
}