Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test system calls from the rake task

Suppose I have a pretty simple Rake task:

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

I try testing it by stubbing the ::Kernel.system method call:

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

But the method seems not to be stubbed at all. Instead, I run into the infinite cycle of iterations calling the test suite.

What's wrong with it, and howto stub system calls properly?

like image 521
Andrew Kozin Avatar asked Oct 14 '25 10:10

Andrew Kozin


1 Answers

Note that Kernel is a module which is included into every ruby Object. And Kernel#system is an instance method (not a class method).

One solution (although discouraged by rspec maintainers) is to use "Any instance":

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

In order to use regular expect or allow, you will need the actual instance of the object which is receiving the message. For a Rake task this will be cumbersome (although not impossible - see this question) - they are executed in the toplevel context.

I would propose that you encapsulate your system calls into utility class methods and expect those. It would make the testing easier and you have explicit classes & instances to work with.

like image 126
czak Avatar answered Oct 17 '25 17:10

czak