如何使用rspec为HighLine gem测试IO?

时间:2019-02-27 11:56:36

标签: ruby highline

我有一堂课

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

如何测试exit_or_continue方法?

1 个答案:

答案 0 :(得分:0)

据我了解,您想根据用户输入来测试exit_or_continue方法。在此方法中,有两个主要的重要事项。其中之一是@cli.ask所做的用户输入,另一种是exit方法,如果用户输入为quit则退出程序。

要测试这些流程,我们需要同时对Kernel.exitHighLine#ask方法进行存根。 首先,我们在Kernel.exit类的实例中重写Asker方法。 Kernel模块包含在Object类中,每个类都在ruby中隐式扩展Object类。因此,我们的Asker类默认具有Kernel的方法。

为什么我们在exit类的实例中存根Asker方法是因为如果我们全局存根(在内核中),这将导致意外的问题。而且,除非我们对这个方法进行存根处理,否则rspec会退出,并且其余测试不会运行。

第二,我们需要对HighLine#ask方法进行存根处理,以等待客户端的输入。 HighLine#ask是方法,它在幕后使用Kernel.gets。通过使用此方法,基本上我们说“ 请返回此值,不要等待用户输入。”。换句话说,使用@cli.stub(ask: 'quit')会返回quit或您想要的任何内容而不会提示任何内容。

因此,我认为以下测试将满足您的需求。如果您遇到任何问题,请随时发表评论。

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