Далее мы переходим к нашему последнему, самому большому тесту, $5 + 1 °CHF. В данной главе мы применили несколько важных технологий:
• добавили параметр, который может нам понадобиться;
• удалили дублирование между кодом и тестами;
• написали тест (testArrayEquals), чтобы проверить порядок функционирования встроенной операции Java;
• создали вспомогательный закрытый (private) класс, не обладающий собственными тестами;
• допустили ошибку при рефакторинге и написали еще один тест, чтобы изолировать проблему.
8 Используя игру слов (английское change означает как «изменение», так и «обмен»), автор намекает на свою знаменитую книгу-бестселлер
15. Смешение валют
$5 + 1 °CHF = $10, если курс обмена 2:1
Операция $5 + $5 возвращает объект Money
Теперь мы готовы написать тест, с которого все началось, – $5 + 1 °CHF:
public void testMixedAddition() {
Expression fiveBucks = Money.dollar(5);
Expression tenFrancs = Money.franc(10);
Bank bank = new Bank();
bank.addRate("CHF", "USD", 2);
Money result = bank.reduce(fiveBucks.plus(tenFrancs), "USD");
assertEquals(Money.dollar(10), result);
}
Именно такой код нам хотелось бы написать. К сожалению, мы сразу же получаем кучу ошибок компиляции. Обобщая код в процессе перехода от Money к Expression, мы оставили много висящих хвостов, на которые я, конечно же, обратил внимание, но решил вас не беспокоить. Теперь настало время заняться устранением дефектов.
Мы не сможем достаточно быстро обеспечить компиляцию предыдущего теста. Как только мы внесем в код первое изменение, нам потребуется внести в код еще изменения, и так далее. Теперь мы можем двигаться дальше одним из двух путей. Мы можем заставить тест работать быстро, для этого надо написать более специфичный тест и затем выполнить обобщение. Второй путь: довериться компилятору и с его помощью найти все ошибки. Давайте попробуем действовать медленно (на практике я внес бы в код все необходимые изменения за один раз).
public void testMixedAddition() {
Money fiveBucks = Money.dollar(5);
Money tenFrancs = Money.franc(10);
Bank bank = new Bank();
bank.addRate("CHF", "USD", 2);
Money result = bank.reduce(fiveBucks.plus(tenFrancs), "USD");
assertEquals(Money.dollar(10), result);
}
Тест терпит неудачу. Мы получаем 15 USD вместо 10 USD. Дело в том, что метод Sum.reduce() не выполняет приведение аргументов:
Sum
public Money reduce(Bank bank, String to) {
int amount = augend.amount + addend.amount;
return new Money(amount, to);
}
Если выполнить приведение обоих аргументов, тест должен сработать:
Sum
public Money reduce(Bank bank, String to) {
int amount= augend.reduce(bank, to). amount
+ addend.reduce(bank, to). amount;
return new Money(amount, to);
}
И действительно, тест срабатывает. Теперь мы можем заменить тип Money на тип Expression. Чтобы избежать взаимовлияний, мы начнем издалека и будем двигаться в направлении тестирующего кода. Итак, поля augend и addend теперь могут иметь тип Expression:
Sum
Expression augend;
Expression addend;
Аргументы конструктора тоже могут иметь тип Expression:
Sum
Sum(Expression augend, Expression addend) {
this.augend = augend;
this.addend = addend;
}
(Класс Sum начинает напоминать мне шаблон «Компоновщик» (Composite), однако еще не настолько, чтобы я захотел обобщить его.) С классом Sum, пожалуй, закончили, а что насчет Money?
Аргумент метода plus() может иметь тип Expression:
Money
Expression plus(Expression addend) {
return new Sum(this, addend);
}
Метод times() может возвращать значение типа Expression:
Money
Expression times(int multiplier) {
return new Money(amount * multiplier, currency);
}
Это означает, что операции plus() и times() должны входить в состав интерфейса Expression. С классом Money закончили. Теперь можно изменить аргументы метода plus() в реализации теста:
public void testMixedAddition() {
Money fiveBucks = Money.dollar(5);
Expression tenFrancs = Money.franc(10);
Bank bank = new Bank();
bank.addRate("CHF", "USD", 2);
Money result = bank.reduce(fiveBucks.plus(tenFrancs), "USD");
assertEquals(Money.dollar(10), result);
}
Объект tenFrancs теперь принадлежит типу Expression, а это значит, что мы должны внести в код некоторые изменения. К счастью, компилятор подсказывает нам, что именно мы должны сделать. Прежде всего вносим изменение:
public void testMixedAddition() {
Expression fiveBucks = Money.dollar(5);
Expression tenFrancs = Money.franc(10);
Bank bank = new Bank();
bank.addRate("CHF", "USD", 2);
Money result = bank.reduce(fiveBucks.plus(tenFrancs), "USD");
assertEquals(Money.dollar(10), result);
}
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии