Mocking Backticks with RR and AAA
In my adventures through RubyLand, I’ve been using the excellent RR test double framework together with RSpec, for some really expressive tests. The other day I was writing a test to prove that a class had invoked a shell command with the correct command-line. I knew there would be some way of mocking the backtick operator in Ruby, but for once RR was working against me. I found this post on the astrails blog to be the key.
It wasn’t quite enough for me though. I like to test in an AAA style, and what I wanted was the following:
describe "My class" do
before do
# Set up stubs
# Invoke the action
end
it "should call some web service" do
# Simple assertion
end
it "should invoke the shell command" do
# How do I make this assertion?
end
end
Using the information I already knew, I could set up a mock which would automatically fail if the command wasn’t invoked, but I didn’t want that embedded in the before
block. If I changed it to a stub, which would accept any command, how could I verify it later on?
Digging into the code of RR revealed that calling my_object.should have_received.my_method()
simply uses method_missing
on the InvocationMatcher class. I could invoke that directly and make an assertion on the command that should have been run:
before do
stub(@target).__double_definition_create__.call(:`) { "some fake output" }
@target.do_action
end
it "should invoke the shell command" do
expected_command = "echo 'this is awesome'"
@target.should have_received.method_missing(:`, expected_command)
end