This is a modification of the Rails5 Spec Converter tool to handle converting from RR v1.1.2 to RSpec v3.6.0 syntax for mocking and stubbing. This is a basic implementation to handle the needs of a large codebase of 6000+ tests. It handles most usages but is not exhaustive.
- Installation
- Usage
- Development
- RR
- Manual Cleanup
- Configure RSpec
- License
Install the gem standalone like so:
$ gem install rr-to-rspec-converter
Make sure you've committed everything to Git first, then
$ cd some-project
$ rr-to-rspec-converter
This will update all the files in that directory matching the globs spec/**/*_spec.rb
or test/**/*_test.rb
.
If you want to specify a specific set of files instead, you can run rr-to-rspec-converter path_to_my_files
.
By default it will make some noise, run with rr-to-rspec-converter --quiet
if you want it not to.
After checking out the repo, run bin/setup
to install dependencies. Then, run bundle exec rspec spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
The following lists each RR API method and the conversion that is applied. Some cases are not handled. To see which ones, search for unhandled
in this document.
mock(view).render.with_any_args.twice do |*args|
if args.first == {:partial => "user_info"}
"User Info"
else
"Stuff in the view #{args.inspect}"
end
end
=> expect(object).to receive(:method).with(arguments).and_return(return_val)
Unhandled
Nested usage:
mock.something.mock!.method { result }
=> and_return(double(method: result))
Simple usage:
mock!
=>
double
instance_double("ConsoleNotifier")
class_double("ConsoleNotifier")
object_double(User.new, :save => true)
object_double("MyApp::LOGGER", :info => nil).as_stubbed_const
Then assert expectations with `have_received` or `receive`.
By itself:
x = stub
=> double
With method:
x = stub(object).method.with(args).returns { return_val }
=> allow(object).to receive(:method).with(arguments).and_return(return_val)
Unhandled
=>
instance_double("ConsoleNotifier")
class_double("ConsoleNotifier")
object_double(User.new, :save => true)
object_double("MyApp::LOGGER", :info => nil).as_stubbed_const
Normal usage:
dont_allow(object).method(args)
=> expect(object).not_to receive(:method).with(args)
Inside any_instance_of
block (Unhandled):
any_instance_of(klass) do |o|
dont_allow(object).method(args)
end
=> expect_any_instance_of(klass).not_to receive(:method).with(args)
Unhandled
Unhandled
=>
and_call_original, or
and_wrap_original
allow(Calculator).to receive(:add).and_call_original
allow(Calculator).to receive(:add).with(2, 3).and_return(-5)
expect(API).to receive(:solve_for).and_wrap_original { |m, *args| m.call(*args).first(5) }
expect(API.solve_for(100)).to eq [1,2,3,4,5]
Unhandled
=> instance_of
Unhandled
any_instance_of(User) do |u|
stub(u).valid? { false }
end
or
any_instance_of(User, :valid? => false)
or
any_instance_of(User, :valid? => lambda { false })
=>
allow_any_instance_of(klass).to receive_messages(:method => return_value)
expect_any_instance_of(klass).to receive_messages(:method => return_value)
allow_any_instance_of(klass).to receive(:method => return_value)
expect_any_instance_of(klass).to receive(:method => return_value)
mock(PetitionGroup).find.with_any_args.returns(petition_group)
=> with(any_args)
=> with(no_args)
=>
times(0) => expect().not_to receive()
times(1) => once
times(2) => twice
times(n) => exactly(n).times **Unhandled**
times(any_times) => allow().to receive() OR at_least(:once)
Converts to at_least(:once)
but this interpretation may be incorrect. The intention of the test may be to allow
the message to be received - in which case mock
should not have been used.
.any_times
.times(any_times)
=> allow().to receive() OR at_least(:once)
mock(PetitionGroup).find.with_any_args.returns(petition_group)
=> and_return
Unhandled
=> with
=> expect(object).not_to receive(:method)
=> once
=>
at_least(0) => Use `allow` instead of `expect` **Unhandled**
at_least(1) => at_least(:once)
at_least(2) => at_least(:twice)
at_least(n) => at_least(n).times
=>
at_most(1) => at_most(:once)
at_most(2) => at_most(:twice)
at_most(n) => at_most(n).times
=> anything
=> kind_of
=> kind_of(Numeric)
=> boolean
=> duck_type
=> hash_including
Use RSpec satisfy
method. Would need to rewrite to use arguments from block, which alters the intent of the test. Will probably require manual fixes post conversion.
=> satisfy
=> hash_including
=> rr_satisfy
=> removes line
- Remove all comments that reference
/\brr\b/i
- Remove 'rr' from Gemfile
- Remove
config.mock_with :rr
fromspec/spec_helper.rb
RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end
The gem is available as open source under the terms of the MIT License.