Проблема в том, что если вы нажмете на игрока, он вернет ноль при вызове capacity
. Вам нужно изменить так:
player.should_receive(:capacity).and_return(0)
player.should_receive(:capacity=).with(1)
Чтобы понять почему, давайте разберем, что происходит в вашем коде. Будет легче увидеть проблему, если мы расширим -=
до:
player.capacity = player.capacity - 1
С вашим заглушенным игроком это становится так:
player.capacity = nil - 1
Именно на это и жалуется RSpec.
Теперь позвольте мне предложить лучший способ написания теста. Ваш тест просто отражает вашу реализацию, он не тестирует метод. Под этим я подразумеваю, что он не проверяет, что метод apply
увеличивает вместимость игрока на единицу - он проверяет, что apply
вызывает capacity
, а затем capacity=
. Вы можете подумать, что это одно и то же, но это только потому, что вы знаете, как реализовали метод.
Вот как бы я написал тест:
it "increments a player's capacity" do
player = Player.new # notice that I use a real Player
player.capacity = 0
subject.apply(player)
player.capacity.should == 1
end
Я использовал реальный объект Player
вместо настройки заглушки, потому что я предполагаю, что реализация Player#capacity
- это просто средство доступа, и там нет логики вмешиваться в мой тест. Риск использования заглушек состоит в том, что иногда заглушки становятся даже более сложными, чем реальные объекты (как в этом случае, я бы сказал,), и это означает, что более вероятно, что ваш тест неверен, чем ваш реальный код.
Вы также можете написать такой тест, если хотите использовать полную выразительность RSpec:
it "increments a player's capacity" do
player = Player.new
player.capacity = 0
expect { subject.apply(player) }.to change { player.capacity }.to(1)
end