An open API service indexing awesome lists of open source software.

https://github.com/kjvarga/rr-to-rspec-converter

Convert from RR to RSpec for mocking and stubbing
https://github.com/kjvarga/rr-to-rspec-converter

Last synced: about 2 months ago
JSON representation

Convert from RR to RSpec for mocking and stubbing

Awesome Lists containing this project

README

          

# RR to RSpec Converter

This is a modification of the [Rails5 Spec Converter](https://github.com/tjgrathwell/rr-to-rspec-converter) tool to handle converting from [RR v1.1.2](https://github.com/rr/rr/blob/master/doc/03_api_overview.md) to [RSpec v3.6.0](https://relishapp.com/rspec/rspec-mocks/v/3-6/docs) 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](#installation)
* [Usage](#usage)
* [Development](#development)
* [RR](#rr)
+ [Mocking and Stubbing](#mocking-and-stubbing)
- [#mock](#mock)
- [#mock!](#mock-1)
- [#stub](#stub)
- [#stub!](#stub-1)
- [#dont_allow](#dont_allow)
- [#dont_allow!](#dont_allow-1)
- [#proxy](#proxy)
- [#proxy!](#proxy-1)
- [#instance_of](#instance_of)
- [#instance_of!](#instance_of-1)
- [#any_instance_of](#any_instance_of)
- [#with_any_args](#with_any_args)
- [#with_no_args](#with_no_args)
- [#times](#times)
- [#any_times](#any_times)
- [#returns](#returns)
- [#yields](#yields)
- [#with](#with)
- [#never](#never)
- [#once](#once)
- [#at_least](#at_least)
- [#at_most](#at_most)
+ [Matchers](#matchers)
- [#anything](#anything)
- [#is_a](#is_a)
- [#numeric](#numeric)
- [#boolean](#boolean)
- [#duck_type](#duck_type)
- [#hash_including](#hash_including)
- [#rr_satisfy](#rr_satisfy)
+ [Module References](#module-references)
- [RR::WildcardMatchers::HashIncluding](#rrwildcardmatchershashincluding)
- [RR::WildcardMatchers::Satisfy](#rrwildcardmatcherssatisfy)
- [RR.reset](#rrreset)
* [Manual Cleanup](#manual-cleanup)
* [Configure RSpec](#configure-rspec)
* [License](#license)
## Installation

Install the gem standalone like so:

$ gem install rr-to-rspec-converter

## Usage

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.

## Development

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.

## RR

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.

### Mocking and Stubbing

#### #mock

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)

#### #mock!

**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`.

#### #stub

[Rspec doubles](https://relishapp.com/rspec/rspec-mocks/v/3-8/docs/basics/partial-test-doubles)

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)

#### #stub!

**Unhandled**

=>
instance_double("ConsoleNotifier")
class_double("ConsoleNotifier")
object_double(User.new, :save => true)
object_double("MyApp::LOGGER", :info => nil).as_stubbed_const

#### #dont_allow

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)

#### #dont_allow!

**Unhandled**

#### #proxy

**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]

#### #proxy!

**Unhandled**

#### #instance_of

=> instance_of

#### #instance_of!

**Unhandled**

#### #any_instance_of

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)

#### #with_any_args

mock(PetitionGroup).find.with_any_args.returns(petition_group)

=> with(any_args)

#### #with_no_args

=> with(no_args)

#### #times

=>
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)

#### #any_times

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)

#### #returns

mock(PetitionGroup).find.with_any_args.returns(petition_group)

=> and_return

#### #yields

**Unhandled**

#### #with

=> with

#### #never

=> expect(object).not_to receive(:method)

#### #once

=> once

#### #at_least

=>
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

=>
at_most(1) => at_most(:once)
at_most(2) => at_most(:twice)
at_most(n) => at_most(n).times

### Matchers

#### #anything

=> anything

#### #is_a

=> kind_of

#### #numeric

=> kind_of(Numeric)

#### #boolean

=> boolean

#### #duck_type

=> duck_type

#### #hash_including

=> hash_including

#### #rr_satisfy

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

### Module References

#### RR::WildcardMatchers::HashIncluding

=> hash_including

#### RR::WildcardMatchers::Satisfy

=> rr_satisfy

#### RR.reset

=> removes line

## Manual Cleanup

* Remove all comments that reference `/\brr\b/i`
* Remove 'rr' from Gemfile
* Remove `config.mock_with :rr` from `spec/spec_helper.rb`

## Configure RSpec

RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end

## License

The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).