Skip to content
clarkedbPublic

About

Mocking and spying in Ruby's MiniTest framework

Topics

Resources

Contributing

Stars

12 stars

Watchers

1 watching

Forks

Repository files navigation

Grift

gem version build codecov

Mocking and spying in Ruby's MiniTest framework

Installation

Add this line to your application's Gemfile:

gem 'grift'

And then execute:

bundle install

Or install it yourself as:

gem install grift

MiniTest Plugin

We recommend using the plugin so that mocks are cleaned up after each test automatically. The plugin also adds assertions for mocks. To enable the plugin, add the following lines of code to your test_helper file.

class Minitest::Test
  include Grift::MinitestPlugin
end

Or for Ruby on Rails:

class ActiveSupport::TestCase
  include Grift::MinitestPlugin
end

Usage

For complete usage guide, see the docs.

Spy

To "mock" a method and spy on its call args and results without changing the behavior of the method:

my_mock = Grift.spy_on(MyClass, :my_method)

Mock

To mock a method and its return value:

my_mock = Grift.mock(MyClass, :my_method, return_value)

my_spy = Grift.spy_on(MyClass, :my_method)
my_spy.mock_return_value(return_value)

To mock the implementation:

my_spy = Grift.spy_on(MyClass, :my_method)
my_spy.mock_implementation do |arg1, arg2|
    x = do_something(arg1, arg2)
    do_something_else(x) # the last line will be returned
end

or for a method taking keyword arguments:

my_spy = Grift.spy_on(MyClass, :my_method)
my_spy.mock_implementation do |arg1, arg2, **kwargs|
    x = do_something(arg1, arg2, kwargs[:arg3], kwargs[:arg4])
    do_something_else(x) # the last line will be returned
end

Class and instance methods with the same name

When a class responds to a method itself, Grift mocks the class method. That includes methods every class has, like name, to_s, and ==. To mock the instance method instead, pass instance: true to spy_on:

my_mock = Grift.spy_on(MyClass, :name, instance: true).mock_return_value('mocked')

Chaining

You can chain mock_return_value and mock_implementation after initializing the mock.

my_mock = Grift.spy_on(MyClass, :my_method).mock_implementation do |*args, **kwargs|
    do_something(*args, **kwargs)
end
#=> Grift::MockMethod object is returned

Results

To get the results and details of the calls, call calls or results on your mock method object.

# get the number of times the mocked method has been called
my_mock.count
#=> 2

# get args for each call to the method while mocked
my_mock.calls[0].args
#=> ['first_arg1', 'second_arg1']

# get kwargs for each call to the method while mocked
my_mock.calls[0].kwargs
#=> { first_arg1: 'value' }

# get results (return value) for each call to the method while mocked
my_mock.results
#=> ['result1', 'result2']

Assertions

With the MiniTest Plugin included, you can assert on mocks directly in your tests.

assert_mocked MyClass, :my_method
refute_mocked MyClass, :other_method

assert_mock_called my_mock
refute_mock_called my_mock

# passes if any call used exactly these arguments
assert_mock_called_with my_mock, 'first_arg', key: 'value'
refute_mock_called_with my_mock, 'other_arg'

When an assertion fails, the message lists the calls to the mocked method.

Requirements

Grift supports all Ruby versions >= 2.7 (including 4.x versions).

Support

For now Grift is not guaranteed to be compatible with Ruby::Box introduced in Ruby 4.0.0. Support will be added/guaranteed if it is determined that Ruby::Box will move out of the experimental phase.

Development

After forking the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

When developing, to install Grift whith your changes onto your local machine, run bundle exec rake install .

Releasing

Releases are managed by release-please. When releasable commits (feat, fix, perf, or breaking changes; see CONTRIBUTING) land on main, it opens (or updates) a release pull request that bumps lib/grift/version.rb and CHANGELOG.md. For those with write access:

  1. Merge the release pull request, which tags the version and creates the GitHub release
  2. Once CI passes on main, approve the release deployment in GitHub Actions, which pushes the .gem file to rubygems.org via trusted publishing and then deploys the docs

If publishing fails, use "Re-run failed jobs" on the workflow run. "Re-run all jobs" re-runs release-please, which finds the release already exists and skips publishing.

Docs

The docs are generated using YARD and deployed to GitHub Pages after each release. To redeploy them, run the Docs workflow manually with the latest release tag. To build them locally, run BUNDLE_WITH=docs bundle install and then bundle exec yard (output goes to the gitignored docs/ folder).

Contributing

Bug reports and pull requests are welcome on GitHub at clarkedb/grift. Before submitting a pull request, see CONTRIBUTING.

About

Mocking and spying in Ruby's MiniTest framework

Topics

Resources

Contributing

Stars

12 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages