Mock system call in ruby
%x{…}
is Ruby built-in syntax that will actually call Kernel method Backtick (`). So you can redefine that method. As backtick method returns the standard output of running cmd in a subshell, your redefined method should return something similar to that ,for example, a string.
module Kernel
def `(cmd)
"call #{cmd}"
end
end
puts %x(ls)
puts `ls`
# output
# call ls
# call ls
How do I mock or override Kernel.system?
If you are talking about unit tests and use Rspec, you should be able to do it like this:
Kernel.should_receive(:system)
or a little more loose:
Kernel.stub(:system)
More info: https://www.relishapp.com/rspec/rspec-mocks/v/2-13/docs/message-expectations/expect-a-message
How do I stub/mock a call to the command line with rspec?
Here is a quick example I made. I call ls from my dummy class. Tested with rspec
require "rubygems"
require "spec"
class Dummy
def command_line
system("ls")
end
end
describe Dummy do
it "command_line should call ls" do
d = Dummy.new
d.should_receive("system").with("ls")
d.command_line
end
end
How to test system calls from the rake task
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.
Is there a way to set the value of $? in a mock in Ruby?
EDIT: Using Dennis Williamson's suggestion:
command = "(exit 21)"
and use if $?.exitstatus == 0
instead of if $? == 0
Related Topics
How to Spawn a Child Process in Ruby
How to Check Whether a Value in a String Is an Ip Address
Ruby - Determining Method Origins
Properly Converting a Cmyk Image to Rgb with Rmagick
Why Are My Bigdecimal Objects Initialized with Unexpected Rounding Errors
Redis or Mongo for Determining If a Number Falls Within Ranges
How to Find the Ruby Interpreter
What Command Opens Ruby's Repl
How to Resolve Ruby Error (Missing Psych)
What Is the Modern Way to Structure a Ruby Gem
How to Avoid Putting the Magic Encoding Comment on Top of Every Utf-8 File in Ruby 1.9
Bundler Could Not Find Compatible Versions for Gem "Bundler":
Rubygems Do Not Install on Os X Lion
Difference Between 'Self.Method_Name' and 'Class << Self' in Ruby
Error Running '_Rvm_Make Install'
Nokogiri: Select Content Between Element a and B
Creating a Capistrano Task That Performs Different Tasks Based on Role