【问题标题】:Mocking popen3 block form ruby模拟popen3块形式红宝石
【发布时间】:2014-11-20 20:37:28
【问题描述】:

我正在使用 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')

模拟函数不会输入“do”代码,我只剩下一个空数据结构。

我想知道如何正确地做到这一点?

谢谢!

【问题讨论】:

  • 您能提供完整的规格吗?
  • @wicz 我更新了我的帖子
  • 这个规范没有返回任何错误?这有点令人困惑。您将 response 模拟为一个数组,但 expect 如果它是一个哈希则它。而代码本身,您在块内定义output,并在方法结束时返回。它应该返回并出错,因为该变量在块中未定义。或者,也许您现在正在共享整个代码。这样就更难提供帮助了。
  • 对不起,我忘了包括它。 Open3 yielded || to block with arity of 4 是我收到的错误。管道之间的任何内容都是传递给 and_yield 的参数集
  • 我最终用capture3 替换了popen3,至于我在做什么,它有效。不是真正的解决方案,而是一种解决方法

标签: ruby rspec popen3


【解决方案1】:

要为 Chris Reisor 的回答添加更多上下文,这是对我有用的方法:

我有一段代码如下所示。

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

【讨论】:

    【解决方案2】:

    我认为您需要输入“*response”而不是“response”。

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

    这会将 4 个字符串 args 发送到 and_yield(“arity of 4”),而不是一个数组 arg。

    【讨论】:

      猜你喜欢
      • 2018-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      相关资源
      最近更新 更多