多次在 ruby 中插入 'gets'

stubbing 'gets' in ruby multiple times

我有一个简单的问题要问 Ruby 脚本:

def ask question 
  while true
    puts question
    reply = gets.chomp.downcase

    return true if reply == 'yes' 
    return false if reply == 'no'

    puts 'Please answer "yes" or "no".' 
  end
end

puts(ask('Do you like eating tacos?'))

我正在这样测试

describe 'ask' do
  before do
    stub(:puts).with('anything')
    stub(:puts).with('Please answer "yes" or "no".')
    stub(:gets).and_return 'yes'
  end
  it 'returns true when you say yes' do
    expect(ask('anything')).to be true
  end
  it 'returns false when you say no' do
    stub(:gets).and_return 'no'
    expect(ask('anything')).to be false
  end
end

我之前一直在尝试使用 RSpec 3 语法和代码

allow(STDIN).to receive(:gets).and_return 'yes'
allow(Kernel).to receive(:gets).and_return 'yes'
allow(IO).to receive(:gets).and_return 'yes'

和其他变体,但其中 none 有效,只是给我这样的错误:

undefined method `chomp' for nil:NilClass

我在 RSpec 2 语法方面运气更好,所以我启用了它并几乎使上述工作正常。问题是行:puts(ask('Do you like eating tacos?'))。如果它被注释掉,一切都很好,但是它存在我得到这个错误:

Errno::ENOENT: No such file or directory @ rb_sysopen

然后现在

undefined methodchomp' for nil:NilClass`

所以我似乎可以在从 RSpec 调用的方法中存根 'gets',但如果使用它的方法是从 ruby 文件调用的 RSpec ] 正在测试。

有什么想法吗?

啊哈,我想我找到了解决办法!

技巧似乎是 allow_any_instance_of(Kernel).to receive(:gets).and_return 'yes' 并在引入应用程序代码之前在 before 块中调用它 - 就像这样:

describe 'ask' do
  before do
    stub(:puts).with('anything')
    stub(:puts).with('Please answer "yes" or "no".')
    stub(:gets).and_return 'yes'
    allow_any_instance_of(Kernel).to receive(:gets).and_return 'yes'
    require './lib/ask.rb'
  end
  it 'returns true when you say yes' do
    expect(ask('anything')).to be true
  end
  it 'returns false when you say no' do
    allow_any_instance_of(Kernel).to receive(:gets).and_return 'no'
    expect(ask('anything')).to be false
  end
end