RBrandao
RBrandao

Reputation: 142

RSpec stub with unexpected results

I am doing a command line of game of Rock Paper Scissors Lizard Spock in Ruby. I have the matchup method that takes the variables @shape (the hand shape randomly selected by the game) and @player_shape (the hand shape chosen by the player).

My matchup method compares the two shapes and sets the game result to @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

I ran the code many times and it works as expected, but in my spec file, the result I'm getting is not matching the code behavior. Here is the 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

and here is the result:

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

   expected: :player_wins
        got: :draw

   (compared using ==)

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

What I am doing wrong here? I've tried and tried and still can't figure out how to solve this problem.

Upvotes: 0

Views: 61

Answers (1)

ck3g
ck3g

Reputation: 5929

Here

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

and there

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

You're stubbing methods Game#shape and Game#player_shape for game object. But you're using @shape == @player_shape as condition in if statement.

Ruby treats undefined instance variables (those which starts from @) as nil by default.

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

Thus @shape == @player_shape is the same as nil == nil in your case. Which is actually a true. What's why program flow reach @result = :draw line.

To make it work you need to define shape and player_shape methods by using attr_reader, for example, and use them instead of instance variables.

upd

Now replace @shape with shape and @player_shape with player_shape in your code. Be sure you initialise values for them.

Take a look at that Ruby Monk tutorial (or any other articles) about instance vairables to understand how they work

Upvotes: 2

Related Questions