Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save floehopper/3137094 to your computer and use it in GitHub Desktop.
Save floehopper/3137094 to your computer and use it in GitHub Desktop.
Mocha/MiniTest integration options

Mocha/MiniTest integration

I think that the approach @tenderlove has suggested to avoid monkey-patching MiniTest (and the way MiniTest works) means that to use Mocha with MiniTest, you would either need to include the Mocha integration module into every test case, or define your own test case class inheriting from MiniTest::Unit::TestCase.

This works well for Rails (i.e. ActiveSupport), because it already defines a new test case class (ActiveSupport::TestCase) which is a suitable place to include the Mocha integration module.

If we were to go down this route, in non-Rails Ruby projects you'd need to do one of the following...

Option A

    class MyTestCase < MiniTest::Unit::TestCase
      include Mocha::Integration::MiniTest
    end
    
    class TestCaseOne < MyTestCase
      def test_foo
        o = mock
        o.expects(:foo)
      end
    end
    
    class TestCaseTwo < MyTestCase
      def test_bar
        o = mock
        mock.expects(:bar)
      end
    end

Option B

    class TestCaseOne < MiniTest::Unit::TestCase
      include Mocha::Integration::MiniTest
      def test_foo
        o = mock
        o.expects(:foo)
      end
    end

    class TestCaseTwo < MiniTest::Unit::TestCase
      include Mocha::Integration::MiniTest
      def test_foo
        o = mock
        o.expects(:foo)
      end
    end

The explicit-ness and the lack of monkey-patching is clearly beneficial, but do you think the above options are too onerous compared to the current behaviour where MiniTest::Unit::TestCase itself is monkey-patched and you could simply do the following :-

    require "minitest/unit"
    require "mocha"
    
    class TestCaseOne < MiniTest::Unit::TestCase
      def test_foo
        o = mock
        o.expects(:foo)
      end
    end

    class TestCaseTwo < MiniTest::Unit::TestCase
      def test_foo
        o = mock
        o.expects(:foo)
      end
    end
@floehopper
Copy link
Author

Or how about this rather crazy option C :-

    class TestCaseOne < Mocha(MiniTest::Unit::TestCase)
      def test_foo
        o = mock
        o.expects(:foo)
      end
    end

    class TestCaseTwo < Mocha(MiniTest::Unit::TestCase)
      def test_foo
        o = mock
        o.expects(:foo)
      end
    end

@chrisroos
Copy link

How does the use of Mocha with rspec and bacon compare to the options above?

@floehopper
Copy link
Author

Using Mocha with Rspec works like this :-

# Gemfile
source :rubygems

gem "rspec-core"
gem "rspec-expectations"
gem "mocha"

# spec.rb
require "bundler/setup"
require "rspec/core"

RSpec.configure do |config|
  config.mock_framework = :mocha
end

describe "mocking" do
  it "foo" do
    o = mock
    o.expects(:foo)
  end
end

The configuration setting causes Rspec to require "mocha/standalone" and "mocha/object" which is the equivalent of require "mocha/api" and "mocha/object" which is in turn the equivalent of require "mocha_standalone".

@floehopper
Copy link
Author

And with Bacon it works like this :-

# Gemfile
source :rubygems

gem "bacon"
gem "mocha-on-bacon"
gem "mocha"

# spec.rb
require "bundler/setup"
require "bacon"
require "mocha-on-bacon"

describe "mock" do
  it "foo" do
    o = mock
    o.expects(:foo)
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment