RSpec存根具有意外结果

时间:2015-07-23 02:14:32

标签: ruby rspec

我在Ruby中使用Rock Paper Scissors Lizard Spock的游戏命令行。我有matchup方法,它采用变量@shape(游戏随机选择的手形)和@player_shape(玩家选择的手形)。

我的matchup方法比较两种形状并将游戏结果设置为@result

class Game
  SHAPES = [:rock, :paper, :scissors, :lizard, :spock]
  attr_reader :shape, :player_shape, :status

  # ...

  def matchup
    if @shape == @player_shape
      @result = :draw
    else
      case @player_shape
      when :rock
        @result = (@shape == :scissors || @shape == :lizard) ? :player_wins : :game_wins
      when :paper
        @result = (@shape == :rock || @shape == :spock) ? :player_wins : :game_wins
      when :scissors
        @result = (@shape == :paper || @shape == :lizard) ? :player_wins : :game_wins
      when :lizard
        @result = (@shape == :paper || @shape == :spock) ? :player_wins : :game_wins
      when :spock
        @result = (@shape == :rock || @shape == :scissors) ? :player_wins : :game_wins
      end
    end
  end

  # ...
end

我多次运行代码并且按预期工作,但在我的spec文件中,我得到的结果与代码行为不匹配。这是规范:

describe Game do
  subject(:game) { Game.new }
  # ...
  describe "#matchup" do
    context "game chooses rock" do
      before do
        allow(game).to receive(:shape).and_return(:rock)
      end

      it "sets result as :player_wins if the game chooses paper" do
        allow(game).to receive(:player_shape).and_return(:paper)

        game.matchup

        expect(game.result).to eq(:player_wins)
     end
    end
  end
end

以下是结果:

Failure/Error: expect(game.result).to eq(:player_wins)

   expected: :player_wins
        got: :draw

   (compared using ==)

   Diff:
   @@ -1,2 +1,2 @@
   -:player_wins
   +:draw

我在这里做错了什么?我已经尝试过但仍然无法弄清楚如何解决这个问题。

1 个答案:

答案 0 :(得分:2)

下面

allow(game).to receive(:shape).and_return(:rock)

然后

allow(game).to receive(:player_shape).and_return(:paper)

您为Game#shape对象存储方法Game#player_shapegame。 但您在@shape == @player_shape声明中使用if作为条件。

Ruby默认将未定义的实例变量(从@开始的变量)视为nil

→ irb
irb(main):001:0> @shape
=> nil

因此@shape == @player_shape与您案例中的nil == nil相同。实际上是true。计划流程达到@result = :draw行的原因是什么。

要使其工作,您需要使用attr_reader来定义shapeplayer_shape方法,例如,使用它们而不是实例变量。

<强> UPD

现在将@shape替换为shape,将@player_shape替换为代码中的player_shape。确保初始化它们的值。

查看关于实例可变品的that Ruby Monk tutorial(或任何其他文章)以了解它们的工作原理