0

I am trying to test if an instance variable saves input from user but I cant figure out how. I expect the test to pass but it fails and outputs expected "joe" got: "" to the terminal. Here is the method, I want to test:

def get_names
    while Player.players < 2
      while name.length <= 2
        puts 'Each player must choose a name'
        print 'Enter a name: '
        @name = gets.chomp
      end

      unless name == ''
        @player1 == '' ? @player1 = Player.new(name) : @player2 = Player.new(name)
        name = ''
        puts 'Name have been saved successfully'
      end
    end
  end

And here is the rspec test suite:

describe Game do
  subject(:game_names) { described_class.new }

  describe '#get_names' do
    context 'when a user inputs name' do
      it 'saves in name instance variable' do
        allow(game_names).to receive(:gets).and_return('joe')
        name = game_names.instance_variable_get(:@name)

        expect(name).to eq 'joe'

        game_names.get_names
      end
    end
  end
end

I gave tried mocking and stubbing the class, the method and the variable, but I can't get it to work. This is my first time writing tests.

2
  • It's unclear what you mean by "can't get it to work". Does the test fail? Do you get an error? Commented Dec 21, 2022 at 15:40
  • The test fails and outputs to the terminal: expected "joe" got: "" yet I expected it to pass Commented Dec 21, 2022 at 17:12

2 Answers 2

1

Without knowing what the rest of your Game and Player classes look like. I would say that you may have an execution order problem in your tests. I am basing the following on the assumption that you might not have a @name instance variable in your initialize method.

So in your tests, you're stubbing the call to gets and returning 'joe' which is cool and exactly what you want. But the next line after that goes and gets the instance variable @name which doesn't exist in the class at that moment because the method which sets that instance variable up hasn't been called yet. And undeclared instance variables will always hold the value, nil.

So you're essentially comparing nil to 'joe' which will never pass.

What you want to do is move game_names.get_names under the allow followed by the instance_variable_get line, and lastly the expect assertion.

describe Game do
  subject(:game_names) { described_class.new }

  describe '#get_names' do
    context 'when a user inputs name' do
      it 'saves in name instance variable' do
        allow(game_names).to receive(:gets).and_return('joe')
        game_names.get_names

        name = game_names.instance_variable_get(:@name)
        expect(name).to eq 'joe'
      end
    end
  end
end
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for the answer. The @name is in the initialize method but and can game_names.get_names be moved anywhere in the test?
What value does @name in the initialize hold? And I wouldn't say that game_names.get_names can be moved anywhere, it really depends.
Empty string @name = ''
Then I would assume the test fails with something like expected "joe" got: "" right? The explanation I provided above still holds true. game_names.get_names is what is setting up the @name that you want to use for comparison and therefore that method needs to be called before trying to retrieve that instance variable. With the changes I suggested, does the test pass or still fail?
It still getting ""
|
0

The bug was in the name assignment to empty string after saving input, so I commented it out and the test passed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.