jejgmq
Last Updated: February 25, 2016
·
2.314K
· 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