Last Updated: February 25, 2016
·
3.682K
· mfpiccolo

Better stubbing with mocha.

In the world of TDD any way to make testing easier I get excited about. Here is a new trick that I just learned using mocha.

We all know the benefits of stubbing methods and giving return values. What I did not know until now is that mocha #stubs accepts a hash where the keys are methods that will be stubbed and the values will be the returned values.

Object.stubs(stubbed_method: :return_value)

If you have a method where an object will call several methods before completion you can use #stubs with a hash for the test. The real life example I used this in was a test that rendered a view that had an object calling a ton of methods like #name, #amount, ect. Some of the methods I wanted a return value and some I didn't care but I wanted them all stubbed and I could do so easily with stubs and a hash.

Here is an example:

Classes:

require "minitest"
require "mocha"

class Fake
end

class Foo

 def bar
 fake = Fake.new
 [fake.jump("high"), fake.run("fast"), fake.hop("far")]
 end

 # Defines #jump, #run and #hop for instances of Fake that turns 
 # the argument passed into a symbol
 symbolify = lambda {|arg| arg.to_sym }
 %w(jump run hop).each do |meth|
 Fake.send(:define_method, meth, &symbolify)
 end
end

Tests:

describe Foo do

 describe "#bar" do
 describe "when stubing out the methods" do
 before do
 return_a, return_b, return_c = :low, :slow, :near
 Fake.any_instance.stubs(
 jump: return_a,
 run: return_b,
 hop: return_c
 )
 end

 it "should return a bunch of mocks" do
 Foo.new.bar.must_equal [:low, :slow, :near]
 end
 end

 describe "without stubing the methods" do
 it "will return the proper aray" do
 Foo.new.bar.must_equal [:high, :fast, :far]
 end
 end
 end
end