Mark Needham

Thoughts on Software Development

Ruby: Mocking or stubbing methods on the system under test

with 5 comments

An approach to testing which I haven’t seen before and am therefore assuming is more specific to Ruby is the idea of stubbing or mocking out functions on the system under test.

I’ve come across a couple of situations where this seems to be done:

  1. When stubbing out calls to methods which are being mixed into the class via a module
  2. When stubbing out calls to private methods within the class

I think the first approach is fine because typically we’ll have a direct test against that module’s methods elsewhere and it doesn’t make much sense to test the same thing again.

I initially liked the second approach as well because it simplifies the spec we’re writing.

For example if we have this code:

class FoosController : ApplicationController
   def index
      populate_something
   end
 
   private
 
   def populate_something
      @something = Something.find(...)    
   end
end

Then by stubbing out ‘populate_something’ we can write a spec like this:

describe FoosController do
   it "should populate something" do
      controller.stub(:populate_something) # and so on
 
      get :index
   end
end

Rather than:

describe FoosController do
   it "should populate something" do
      Something.stub(:find) # and so on
 
      get :index
   end
end

This is a fairly contrived example of course and the temptation to stub out a method on the system under test increases as the amount of dependencies and the complexity of them increases.

The problem we create for ourselves is that if we want to change the internal structure of our class, perhaps by inlining those private methods, then we’ll end up with specs failing even if the external behaviour remains exactly the same.

My current thinking is that if we get in a situation where we want to stub out something on the system under test then it’d probably be better to listen to that pain and try and work out a cleaner way of solving the problem.

Written by Mark Needham

October 24th, 2010 at 5:30 pm

Posted in Ruby

Tagged with

  • James Fraser

    To expand on your final point, I think any private methods in a controller that are much more complicated than your standard AR find stuff are probably a good candidate for moving out of the controller and into the model.

    Difficulty in stubbing out a lot of calls in a spec is always a trigger for me to consider putting my controller on a diet.

  • Pingback: Communication: Logging levels at Mark Needham

  • Pingback: Mark Needham: Communication: Logging levels | Software Secret Weapons

  • http://betarelease.github.com Sudhindra Rao

    HI Mark,
    Stubbing the class under test is a strict no no.. be it ruby or otherwise. This specific way of doing things is an antipattern and ruby makes itself amenable to such things has proliferated beyond control. +1 on James Fraser’s comment – if you have a private method on your controller you are missing some behaviour in your model so move it to a model or create a new one. Just because you can call send does not permit anyone to push behaviour into their private methods and test them by calling send. I would call it laziness on the developer/team’s part for not being diligent about this and refactoring when needed.

    -Sudhindra

  • http://www.markhneedham.com Mark Needham

    @Sudhindra – ok cool that’s what I was thinking but I wasn’t sure whether or not it was considered a bad thing to do in Ruby or not.

    I agree with you and James re: private methods although recently read an interesting post refuting that – http://kailuowang.blogspot.com/2010/08/testing-private-methods-in-rspec.html