Mocks and Stubs with Rails' MiniTest

Using mocks and stubs in MiniTest for Rails

Hello from the Rails world! I used to write Java and tested with JUnit, but after changing jobs I now use Ruby and PHP. Here is how I use MiniTest—the default unit-testing framework in Rails—to mock and stub things.

What is MiniTest?

A minimal example looks like this:

test "test case 001" do
  assert_equal 'expected', 'value under test'
end

You put the method call or return value under test on the right-hand side. In this example I used assert_equal, which checks equality. Other handy assertions include:

AssertionDescription
assertPasses when the argument is truthy
assert_emptyPasses when the argument is empty
assert_raisePasses when the specified exception class is raised

That is enough for most basic cases, but explore the docs for more.

What is a mock?

Let’s make a simple mock.

Using MiniTest::Mock

First require MiniTest at the top of your test file:

require 'minitest/autorun'

Now you can mock things. Suppose we have a Const class with a constant VAR:

class Const
  VAR = 'before'
end

You can stub it like this:

test "test case 002" do
  mock = MiniTest::Mock.new
  mock.expect :call, "Value we want during the test", []
  Const.stub :VAR, mock do
    # Inside this block, Const::VAR returns "Value we want during the test".
  end
end

That helps when you are chasing coverage or isolating unit tests.

You can also provide the replacement value directly without MiniTest::Mock:

test "test case 003" do
  Const.stub :VAR, "Value we want during the test" do
    # Within this block, Const::VAR is set to the provided value.
  end
end

Check the official docs for more details.