{"id":20710695,"url":"https://github.com/kjvarga/rr-to-rspec-converter","last_synced_at":"2025-10-09T21:36:37.993Z","repository":{"id":56892774,"uuid":"163026945","full_name":"kjvarga/rr-to-rspec-converter","owner":"kjvarga","description":"Convert from RR to RSpec for mocking and stubbing","archived":false,"fork":false,"pushed_at":"2019-01-04T23:08:12.000Z","size":126,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-08T04:56:34.354Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kjvarga.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-24T22:27:07.000Z","updated_at":"2021-11-22T19:17:45.000Z","dependencies_parsed_at":"2022-08-20T16:10:28.244Z","dependency_job_id":null,"html_url":"https://github.com/kjvarga/rr-to-rspec-converter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kjvarga/rr-to-rspec-converter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kjvarga%2Frr-to-rspec-converter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kjvarga%2Frr-to-rspec-converter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kjvarga%2Frr-to-rspec-converter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kjvarga%2Frr-to-rspec-converter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kjvarga","download_url":"https://codeload.github.com/kjvarga/rr-to-rspec-converter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kjvarga%2Frr-to-rspec-converter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001980,"owners_count":26083259,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-17T02:12:53.953Z","updated_at":"2025-10-09T21:36:37.977Z","avatar_url":"https://github.com/kjvarga.png","language":"Ruby","funding_links":[],"categories":["Converters"],"sub_categories":[],"readme":"# RR to RSpec Converter\n\nThis 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.\n\n  * [Installation](#installation)\n  * [Usage](#usage)\n  * [Development](#development)\n  * [RR](#rr)\n    + [Mocking and Stubbing](#mocking-and-stubbing)\n      - [#mock](#mock)\n      - [#mock!](#mock-1)\n      - [#stub](#stub)\n      - [#stub!](#stub-1)\n      - [#dont_allow](#dont_allow)\n      - [#dont_allow!](#dont_allow-1)\n      - [#proxy](#proxy)\n      - [#proxy!](#proxy-1)\n      - [#instance_of](#instance_of)\n      - [#instance_of!](#instance_of-1)\n      - [#any_instance_of](#any_instance_of)\n      - [#with_any_args](#with_any_args)\n      - [#with_no_args](#with_no_args)\n      - [#times](#times)\n      - [#any_times](#any_times)\n      - [#returns](#returns)\n      - [#yields](#yields)\n      - [#with](#with)\n      - [#never](#never)\n      - [#once](#once)\n      - [#at_least](#at_least)\n      - [#at_most](#at_most)\n    + [Matchers](#matchers)\n      - [#anything](#anything)\n      - [#is_a](#is_a)\n      - [#numeric](#numeric)\n      - [#boolean](#boolean)\n      - [#duck_type](#duck_type)\n      - [#hash_including](#hash_including)\n      - [#rr_satisfy](#rr_satisfy)\n    + [Module References](#module-references)\n      - [RR::WildcardMatchers::HashIncluding](#rrwildcardmatchershashincluding)\n      - [RR::WildcardMatchers::Satisfy](#rrwildcardmatcherssatisfy)\n      - [RR.reset](#rrreset)\n  * [Manual Cleanup](#manual-cleanup)\n  * [Configure RSpec](#configure-rspec)\n  * [License](#license)\n## Installation\n\nInstall the gem standalone like so:\n\n    $ gem install rr-to-rspec-converter\n\n## Usage\n\nMake sure you've committed everything to Git first, then\n\n    $ cd some-project\n    $ rr-to-rspec-converter\n\nThis will update all the files in that directory matching the globs `spec/**/*_spec.rb` or `test/**/*_test.rb`.\n\nIf you want to specify a specific set of files instead, you can run `rr-to-rspec-converter path_to_my_files`.\n\nBy default it will make some noise, run with `rr-to-rspec-converter --quiet` if you want it not to.\n\n## Development\n\nAfter 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.\n\n## RR\n\nThe 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.\n\n### Mocking and Stubbing\n\n#### #mock\n\n    mock(view).render.with_any_args.twice do |*args|\n      if args.first == {:partial =\u003e \"user_info\"}\n        \"User Info\"\n      else\n        \"Stuff in the view #{args.inspect}\"\n      end\n    end\n\n    =\u003e expect(object).to receive(:method).with(arguments).and_return(return_val)\n\n#### #mock!\n\n**Unhandled**\n\nNested usage:\n\n    mock.something.mock!.method { result }\n\n    =\u003e and_return(double(method: result))\n\nSimple usage:\n\n    mock!\n    =\u003e\n      double\n      instance_double(\"ConsoleNotifier\")\n      class_double(\"ConsoleNotifier\")\n      object_double(User.new, :save =\u003e true)\n      object_double(\"MyApp::LOGGER\", :info =\u003e nil).as_stubbed_const\n\n      Then assert expectations with `have_received` or `receive`.\n\n#### #stub\n\n[Rspec doubles](https://relishapp.com/rspec/rspec-mocks/v/3-8/docs/basics/partial-test-doubles)\n\nBy itself:\n\n    x = stub\n\n    =\u003e double\n\nWith method:\n\n    x = stub(object).method.with(args).returns { return_val }\n\n    =\u003e allow(object).to receive(:method).with(arguments).and_return(return_val)\n\n#### #stub!\n\n**Unhandled**\n\n    =\u003e\n      instance_double(\"ConsoleNotifier\")\n      class_double(\"ConsoleNotifier\")\n      object_double(User.new, :save =\u003e true)\n      object_double(\"MyApp::LOGGER\", :info =\u003e nil).as_stubbed_const\n\n#### #dont_allow\n\nNormal usage:\n\n    dont_allow(object).method(args)\n\n    =\u003e expect(object).not_to receive(:method).with(args)\n\nInside `any_instance_of` block (**Unhandled**):\n\n    any_instance_of(klass) do |o|\n      dont_allow(object).method(args)\n    end\n\n    =\u003e expect_any_instance_of(klass).not_to receive(:method).with(args)\n\n#### #dont_allow!\n\n**Unhandled**\n\n#### #proxy\n\n**Unhandled**\n\n    =\u003e\n      and_call_original, or\n      and_wrap_original\n\n      allow(Calculator).to receive(:add).and_call_original\n      allow(Calculator).to receive(:add).with(2, 3).and_return(-5)\n\n      expect(API).to receive(:solve_for).and_wrap_original { |m, *args| m.call(*args).first(5) }\n      expect(API.solve_for(100)).to eq [1,2,3,4,5]\n\n#### #proxy!\n\n**Unhandled**\n\n#### #instance_of\n\n    =\u003e instance_of\n\n#### #instance_of!\n\n**Unhandled**\n\n#### #any_instance_of\n\n    any_instance_of(User) do |u|\n      stub(u).valid? { false }\n    end\n     or\n    any_instance_of(User, :valid? =\u003e false)\n     or\n    any_instance_of(User, :valid? =\u003e lambda { false })\n\n    =\u003e\n\n      allow_any_instance_of(klass).to receive_messages(:method =\u003e return_value)\n      expect_any_instance_of(klass).to receive_messages(:method =\u003e return_value)\n      allow_any_instance_of(klass).to receive(:method =\u003e return_value)\n      expect_any_instance_of(klass).to receive(:method =\u003e return_value)\n\n\n#### #with_any_args\n\n    mock(PetitionGroup).find.with_any_args.returns(petition_group)\n\n    =\u003e with(any_args)\n\n#### #with_no_args\n\n    =\u003e with(no_args)\n\n#### #times\n\n    =\u003e\n      times(0) =\u003e expect().not_to receive()\n      times(1) =\u003e once\n      times(2) =\u003e twice\n      times(n) =\u003e exactly(n).times  **Unhandled**\n      times(any_times) =\u003e allow().to receive() OR at_least(:once)\n\n#### #any_times\n\nConverts 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.\n\n    .any_times\n    .times(any_times)\n\n    =\u003e allow().to receive() OR at_least(:once)\n\n#### #returns\n\n    mock(PetitionGroup).find.with_any_args.returns(petition_group)\n\n    =\u003e and_return\n\n#### #yields\n\n**Unhandled**\n\n#### #with\n\n    =\u003e with\n\n#### #never\n\n    =\u003e expect(object).not_to receive(:method)\n\n#### #once\n\n    =\u003e once\n\n#### #at_least\n\n    =\u003e\n      at_least(0)  =\u003e Use `allow` instead of `expect` **Unhandled**\n      at_least(1)  =\u003e at_least(:once)\n      at_least(2)  =\u003e at_least(:twice)\n      at_least(n)  =\u003e at_least(n).times\n\n#### #at_most\n\n    =\u003e\n      at_most(1)  =\u003e at_most(:once)\n      at_most(2)  =\u003e at_most(:twice)\n      at_most(n)  =\u003e at_most(n).times\n\n### Matchers\n\n#### #anything\n\n    =\u003e anything\n\n#### #is_a\n\n    =\u003e kind_of\n\n#### #numeric\n\n    =\u003e kind_of(Numeric)\n\n#### #boolean\n\n    =\u003e boolean\n\n#### #duck_type\n\n    =\u003e duck_type\n\n#### #hash_including\n\n    =\u003e hash_including\n\n#### #rr_satisfy\n\nUse 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.\n\n    =\u003e satisfy\n\n### Module References\n\n#### RR::WildcardMatchers::HashIncluding\n\n    =\u003e hash_including\n\n#### RR::WildcardMatchers::Satisfy\n\n    =\u003e rr_satisfy\n\n#### RR.reset\n\n    =\u003e removes line\n\n## Manual Cleanup\n\n* Remove all comments that reference `/\\brr\\b/i`\n* Remove 'rr' from Gemfile\n* Remove `config.mock_with :rr` from `spec/spec_helper.rb`\n\n## Configure RSpec\n\n    RSpec.configure do |config|\n      config.mock_with :rspec do |mocks|\n        mocks.verify_partial_doubles = true\n      end\n    end\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkjvarga%2Frr-to-rspec-converter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkjvarga%2Frr-to-rspec-converter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkjvarga%2Frr-to-rspec-converter/lists"}