模仿popen3块格式ruby

模仿popen3块格式ruby,ruby,rspec,popen3,Ruby,Rspec,Popen3,我正在使用rspec在Ruby中开发一些测试用例 我试图模拟popen3函数 但是,虽然仍保留阻塞表单,但我无法捕获预期的输出信息: Class MyClass def execute_command Open3.popen3(command) do |stdin, stdout, stderr, wait_thr| output['wait_thr'] = wait_thr.value while line = stderr.gets ou

我正在使用rspec在Ruby中开发一些测试用例

我试图模拟popen3函数

但是,虽然仍保留阻塞表单,但我无法捕获预期的输出信息:

Class MyClass
  def execute_command
    Open3.popen3(command) do |stdin, stdout, stderr, wait_thr|
      output['wait_thr'] = wait_thr.value
      while line = stderr.gets
         output['stderr'] += line
      end
    end
    return output
  end  
end
为了模拟该函数,我将执行以下操作:

it 'should do something'
  response = []
  response << 'stdin'
  response << 'stdout'
  response << 'test'
  response << 'exit 0'

  # expect
  allow(Open3).to receive(:popen3).with(command).and_yield(response)

  # when
  output = myClassInstance.execute_script

  #then
  expect(output['wait_thr'].to_s).to include('exit 0')
它“应该做点什么”
响应=[]
response我想你需要用“*response”而不是“response”


这将向and_yield发送4个字符串参数(“4的arity”),而不是一个数组。

为了给Chris Reissor的答案添加更多的上下文,这是一种对我有效的方法:

我有一段代码,如下所示

Open3.popen2e(*cmd) do |_, stdout_and_stderr, wait_thr|
  while (line = stdout_and_stderr.gets)
    puts line
  end

  raise NonZeroExitCode, "Exited with exit code #{wait_thr.value.exitcode}" unless wait_thr.value.success?
end
我的测试设置如下所示

let(:wait_thr) { double }
let(:wait_thr_value) { double }
let(:stdout_and_stderr) { double }

before do
  allow(wait_thr).to receive(:value).and_return(wait_thr_value)
  allow(wait_thr_value).to receive(:exitcode).and_return(0)
  allow(wait_thr_value).to receive(:success?).and_return(true)
  allow(stdout_and_stderr).to receive(:gets).and_return('output', nil)
  allow(Open3).to receive(:popen2e).and_yield(nil, stdout_and_stderr, wait_thr)
end

你能提供完整的规范吗?@wicz我已经更新了我的帖子,这个规范没有返回任何错误?这有点令人困惑。您正在将
响应
模拟为一个数组,但是如果它是一个散列,则
期望它。代码本身,在块内定义
输出
,并在方法末尾返回。它应该返回并出错,因为该变量在块外未定义。或者你现在可以分享整个代码。这使得帮助更难。对不起,我忘了把它包括在内<代码>Open3产生| |以4的算术数阻塞
是我收到的错误。管道之间的任何东西都是传递给的一组参数,而_yieldI最终用
capture3
替换了
popen3
,至于我在做什么,它是有效的。这不是一个真正的解决方案,而是一个变通办法
let(:wait_thr) { double }
let(:wait_thr_value) { double }
let(:stdout_and_stderr) { double }

before do
  allow(wait_thr).to receive(:value).and_return(wait_thr_value)
  allow(wait_thr_value).to receive(:exitcode).and_return(0)
  allow(wait_thr_value).to receive(:success?).and_return(true)
  allow(stdout_and_stderr).to receive(:gets).and_return('output', nil)
  allow(Open3).to receive(:popen2e).and_yield(nil, stdout_and_stderr, wait_thr)
end