如何从rake任务测试系统调用

时间:2015-02-02 10:43:03

标签: ruby rspec rake system stub

假设我有一个非常简单的Rake任务:

task :test do
  system "bundle exec rspec spec"
end

我尝试通过存根::Kernel.system方法调用来测试它:

describe "test" do

  before { allow(::Kernel).to receive(:system) }

  it "runs 'bundle exec rspec spec'" do
    expect(::Kernel).to receive(:system).with "bundle exec rspec spec"
    Rake::Task[:test].invoke
  end
end

但这种方法似乎根本没有被删除。相反,我遇到了调用测试套件的无限循环迭代。

它有什么问题,以及如何正确调用系统?

1 个答案:

答案 0 :(得分:4)

请注意Kernel是一个包含在每个ruby Object中的模块。 Kernel#system是一个实例方法(不是类方法)。

一个解决方案(尽管discouraged by rspec maintainers)是使用"任何实例":

it "runs 'bundle exec rspec spec'" do
  expect_any_instance_of(Kernel).to receive(:system).with "bundle exec rspec spec"
  Rake::Task[:test].invoke
end

要使用常规expectallow,您需要接收邮件的对象的实际实例。对于Rake任务来说,这将是繁琐的(虽然并非不可能 - 请参阅this question) - 它们是在顶层环境中执行的。

我建议您将system调用封装到实用程序类方法中,并expect封装。这将使测试更容易,你有明确的类和&与之合作的实例。