【问题标题】:How to test IO with rspec for HighLine gem?如何使用 rspec 为 HighLine gem 测试 IO?
【发布时间】:2019-02-27 11:56:36
【问题描述】:

我有一堂课:

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 方法?

【问题讨论】:

  • @cli.ask 是做什么的?是在等待用户输入吗?
  • @zeitnot 它会打印问题并等待用户输入
  • 所以你想测试输入对吗?

标签: ruby highline


【解决方案1】:

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

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

为什么我们在Asker 类的实例中存根exit 方法是因为如果我们在全局(在内核中)存根它会导致意想不到的问题。更重要的是,除非我们 stub 这个方法 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

【讨论】:

    猜你喜欢
    • 2012-12-24
    • 2012-07-26
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多