Экстремальное программирование. Разработка через тестирование | страница 45




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);