1

I have a class:

class Asker

  def initialize
    @cli = HighLine.new
  end 

  def exit_or_continue
    answer = @cli.ask "Type 'quit' to exit at any time, Press 'Enter' to continue"
    exit(0) if answer == 'quit'
  end
end

How could I test the exit_or_continue method?

Stephen
  • 3,822
  • 2
  • 25
  • 45

1 Answers1

0

As far as I understand you want to test exit_or_continue method depending on user input. In this method, there are two main important things. One of them is the user input that @cli.ask does and other one is exit method that quits the program if the user input is quit.

To test these flow we need to stub both Kernel.exit and HighLine#ask method. Firstly, we override the Kernel.exit method inside the instance of Asker class. The Kernel module is included in the Object class and every class extend Object class implicitly in ruby. So our Asker class has the methods of Kernel by default.

Why we stub the exit method inside the instance of Asker class is this would lead to unexpected problems if we stub it globally(In Kernel). What is more, unless we stub this method rspec quits and the rest of tests are not run.

Secondly, we need to stub HighLine#ask method which waits for input from the client. HighLine#ask is method and this uses Kernel.gets under the hood. By stubbing this method, basically we say 'please return this value and do not wait for user input.'. In other words, with @cli.stub(ask: 'quit') this will return quit or whatever you want without prompt something.

So I think the following test will accomplish your need. If you encounter any problem please do not hesitate to drop a comment.

RSpec.describe Asker do

  describe '#exit_or_continue' do
    before do
      @asker = Asker.new
      @cli = @asker.instance_variable_get('@cli')
      @asker.stub(exit: true) # We override Kernel.exit method inside asker instance
    end

    context 'when user input is quit' do
      it 'returns true' do
        @cli.stub(ask: 'quit') # We stub HighLine#ask method to return quit on behalf of the user.
        expect(@sker.exit_or_continue).to be(true)
      end
    end
    context 'when user is input is NOT quit' do
      it 'returns nil' do
        @cli.stub(ask: 'invalid response') # We stub HighLine#ask method to return invalid response on behalf of the user.
        expect(@sker.exit_or_continue).to be_nil
      end
    end
  end
end
zeitnot
  • 1,304
  • 12
  • 28