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
Private Messages with Faye and Rails
Actionmailer Pass Local Variables to The Erb Template
How to Test Strong Params with Rspec
Gem Ransack Doesn't Return Any Results When Searched with Full Name
Why Do Ruby People Say They Don't Need Interfaces
How to Troubleshoot Memory Bloat at Boot for Rails App
Rake Cucumber and Rake Spec Always Use "Develop" Environment
Seed Images in Heroku with Paperclip
How to Fix Difference in Behavior of Activesupport 3.0.0 Compare to 2.X
Rails How to Create Data Schema Seed Data
Activemodel::Validations on Anonymous Class
Error Generating Source Map - Grunt and SASS Configuration
Hw Impossibility: "Create a Rock Paper Scissors Program in Ruby Without Using Conditionals"
Server Sent Events and Rails Streaming
Asynchronously Iterating Over The Response of a Request Using Thin and Sinatra
Rails/Postgres, 'Foreign Keys' Stored in Array to Create 1-Many Association