在Ruby中测试STDIN

在Ruby中测试STDIN,ruby,testing,rspec,stdin,Ruby,Testing,Rspec,Stdin,我目前正在尝试测试一个基本方法,它从用户(get)接收一些输入并输出(put)。经过一番研究,我找到了一种测试标准输出流的好方法,如下所示: def capture_standard_output(&block) original_stream = $stdout $stdout = mock = StringIO.new yield mock.string.chomp ensure $stdout = original_stream end 我正在测试的方法如下所

我目前正在尝试测试一个基本方法,它从用户(get)接收一些输入并输出(put)。经过一番研究,我找到了一种测试标准输出流的好方法,如下所示:

def capture_standard_output(&block)
  original_stream = $stdout
  $stdout = mock = StringIO.new
  yield
  mock.string.chomp
ensure
  $stdout = original_stream
end
我正在测试的方法如下所示,输出和输入引用我在开始时初始化的IVAR,并指向等效的$stdout和$stdin:

def ask_for_mark
  ouput.puts 'What shall I call you today?'
  answer = input.gets.chomp.capitalize
  answer
end
现在我已经看到了一些STDIN的解决方案,但还没有真正理解其中的任何一个,我肯定不想复制和粘贴。我唯一需要“工作”的是下面的一个,但它没有真正工作,因为当我运行rspec时,它会暂停并等待输入,只需按enter键,它就会通过:

  it "takes user's name and returns it" do
    output = capture_standard_output { game.ask_for_name }
    expect(output).to eq "What shall I call you today?"
    game.input.stub(:gets) { 'joe' }
    expect(game.ask_for_name).to eq 'Joe'
  end
测试STDIN的好方法是什么?我已经盯着屏幕看了一天的大部分时间(不太好,我知道),所以如果能有一个全新的视角和一些帮助,我将不胜感激:-)

更新 对于面临类似问题的人,我采用了不同(更简单)的方法。首先,我将用它们自己的方法分离IO操作

在输入的情况下,在测试中,它可以预先填充所需的数据,因此当发送
GET
消息时,它将返回由换行符
\n
分隔的数据,如下所示:

input = StringIO.new("one\ntwo\n")
=> #<StringIO:0x007f88152f3510>
input.gets
=> "one\n"
input.gets
=> "two\n"
input.gets
=> nil
每种方法都有权衡,但我想我会把这些放在这里,以防有人遇到类似问题或考虑选择。

您可以简单地将stub STDIN:

实际上,您可以使用
STDOUT
,而无需更改
$STDOUT

it "takes user's name and returns it" do
  expect(STDOUT).to receive(:puts).with("What shall I call you today?")
  allow(STDIN).to receive(:gets) { 'joe' }
  expect(game.ask_for_name).to eq 'Joe'
end

我真的不能确定,但是我在使用$stdin/$stdout/StringIO时遇到的一个问题是确保在它们上运行#回放。你在这么做吗

input = StringIO.new
input.puts "joe"
input.rewind
input.gets #=> "joe\n"
it "takes user's name and returns it" do
  expect(STDOUT).to receive(:puts).with("What shall I call you today?")
  allow(STDIN).to receive(:gets) { 'joe' }
  expect(game.ask_for_name).to eq 'Joe'
end
input = StringIO.new
input.puts "joe"
input.rewind
input.gets #=> "joe\n"