The Difference between Mocks and Stubs

Some recent converstations have made me realise that a lot of people are confused by the difference between mocking and stubbing. I’ve realised that I’ve only added to the confusion by calling part of the Mocha library, Stubba.

The difference between mocking and stubbing

Stubbing a method is all about replacing the method with code that returns a specified result (or perhaps raises a specified exception). Mocking a method is all about asserting that a method has been called (perhaps with particular parameters).

If you think about it, it’s difficult (or impossible?) to do mocking without stubbing – you need to return from the mocked method, so that the code under test can complete execution. So mocking libraries tend to implicitly or explicitly allow you to do stubbing.

Mocking and stubbing with Mocha

To stub a method, use the stubs method.
To mock a method, use the expects method.

The difference between Mocha and Stubba

Mocha is a traditional mocking library very much in the JMock mould. Stubba is a separate part of Mocha that allows mocking and stubbing of methods on real (non-mock) classes. It works by moving the method of interest to one side, adding a new stubbed version of the method which delegates to a traditional mock object. You can use this mock object to set up stubbed return values or set up expectations of methods to be called. After the test completes the stubbed version of the method is removed and replaced by the original.

I’m thinking of ditching the name Stubba, because this part of the library is not solely concerned with stubbing. Let me know what you think.

Martin Fowler has a must-read article on why Mocks Aren’t Stubs.

Another great reference is JMocks documentation – in particular Yoga for your Unit Tests.

class ClassUnderTest
  def initialize(dependency)
    @dependency = dependency
  end
  def do_it
    @dependency.execute
  end
end

class Dependency
  def execute
    # complicated code
  end
end

Stubbing example

class MyTest < Test::Unit::TestCase
  class DependencyStub
    def execute
      true
    end
  end
  def test_stubbing_example
    dependency = DependencyStub.new
    class_under_test = ClassUnderTest.new(dependency)
    assert_equal true, class_under_test.do_it
  end
end

Mocking example

class MyTest < Test::Unit::TestCase
  class DependencyMock
    attr_reader :call_count
    def initialize
      @call_count = 0
    end
    def execute
      @call_count += 1
    end
  end
  def test_mocking_example
    dependency = DependencyMock.new
    class_under_test = ClassUnderTest.new(dependency)
    class_under_test.do_it
    assert_equal 1, dependency.call_count
  end
end