Mocking and spying in Ruby's MiniTest framework
Add this line to your application's Gemfile:
gem 'grift'And then execute:
bundle installOr install it yourself as:
gem install griftWe 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
endOr for Ruby on Rails:
class ActiveSupport::TestCase
include Grift::MinitestPlugin
endFor complete usage guide, see the docs.
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)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
endor 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
endWhen 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')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 returnedTo 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']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.
Grift supports all Ruby versions >= 2.7 (including 4.x versions).
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.
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 .
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:
- Merge the release pull request, which tags the version and creates the GitHub release
- Once CI passes on
main, approve thereleasedeployment in GitHub Actions, which pushes the.gemfile 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.
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).
Bug reports and pull requests are welcome on GitHub at clarkedb/grift. Before submitting a pull request, see CONTRIBUTING.