How to Stub/Mock a Call to The Command Line with Rspec

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

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 to mock/stub File.open each_line in ruby / rspec

Try something like this:

RSpec.describe "an example of mock" do
let(:content) { StringIO.new("1\n2\n3") }

specify do
allow(File).to receive(:open).and_yield(content)
# do whatever you want
end
end

How to test stdin for a CLI using rspec

I ended up finding a solution that I think fairly closely mirrors the code for executing instructions from a file. I overcame the main hurdle by finally realizing that I could write cli.stub(:gets).and_return and pass it in the array of commands I wanted to execute (as parameters thanks to the splat * operator), and then pass it the "EXIT" command to finish. So simple, yet so elusive. Many thanks go to this StackOverflow question and answer for pushing me over the line.

Here is the code:

describe "executing instructions from the command line" do
let(:output) { capture(:stdout) { cli.execute } }

context "with valid commands" do
valid_test_data.each do |data|
let(:expected_output) { data[:output] }
let(:commands) { StringIO.new(data[:input]).map { |a| a.strip } }

it "should process the commands and output the results" do
cli.stub(:gets).and_return(*commands, "EXIT")
output.should include(expected_output)
end
end
end
# ...
end

Can I use RSpec to mock stdin/stdout to test console reads & writes?

You can use mocks and have the method called more than once by listing multiple values in the and_return() method. These will be returned, one on each call, in the order given.

STDIN.should_receive(:read).and_return("Your string")

STDIN.should_receive(:read).and_return("value1", "value2", "value3")

You can do similar things with STDOUT:

STDOUT.should_receive(:puts).with("string")

See the RSpec mocking documentation for more information.



Related Topics



Leave a reply



Submit