Ruby 如何使用rspec测试分叉的代码

Ruby 如何使用rspec测试分叉的代码,ruby,tdd,rspec,rspec2,Ruby,Tdd,Rspec,Rspec2,我有以下代码 def start_sunspot_server unless @server pid = fork do STDERR.reopen("/dev/null") STDOUT.reopen("/dev/null") server.run end at_exit { Process.kill("TERM", pid) } wait_until_solr_starts

我有以下代码

  def start_sunspot_server
    unless @server
      pid = fork do
        STDERR.reopen("/dev/null")
        STDOUT.reopen("/dev/null")
        server.run
      end

      at_exit { Process.kill("TERM", pid) }

      wait_until_solr_starts
    end
  end
如何使用rspec有效地进行测试

我一直在想一些事情

Kernel.should_receive(:fork)
STDERR.should_receive(:reopen).with("/dev/null")
STDOUT.should_receive(:reopen).with("/dev/null")
server.should_receive(:run)

etc

我被示例中的
@server
实例变量和
server
方法弄糊涂了,但下面的示例应该可以帮助您找到您想要去的地方:

class Runner
  def run
    fork do
      STDERR.reopen("/dev/null")
    end
  end
end

describe "runner" do
  it "#run reopens STDERR at /dev/null" do
    runner = Runner.new

    runner.should_receive(:fork) do |&block|
      STDERR.should_receive(:reopen).with("/dev/null")
      block.call
    end

    runner.run
  end
end
关键是
fork
消息被发送到
Runner
对象本身,即使它的实现在
内核
模块中

嗯,,
大卫的解决方案对我们不起作用。也许是因为我们没有使用RSPEC2

这就是我们所做的工作

def run
  fork do
    blah
  end
end

describe '#run' do
  it 'should create a fork which calls #blah' do
    subject.should_receive(:fork).and_yield do |block_context|
      block_context.should_receive(:blah)
    end

    subject.run_job
  end
end

我不确定在调用常量(如STDERR)时这将如何应用,但这是我们能够完成fork测试的唯一方法。

它对我有效,我最终也在另一个地方使用了它,没有任何问题,我确信我在这两种情况下都使用了Rspec2。如果我模拟对象,我就无法实现这一点(使用
expect
matcher),但如果我存根对象(使用
allow
matcher),则可以使其工作。如果从未调用存根,测试不会失败,但您会在输出中看到错误。建议通过指定存根应接收的参数使其特定于存根。