rspec-rails: `let(:name)` will conflict with Rails internals for fixtures
What Ruby, Rails and RSpec versions are you using?
Ruby version: 2.7.1 Rails version: 6.1.1 RSpec version: 4.0.2
Observed behaviour
One of my specs started to fail while upgrading rails from 6.0 to 6.1.
I noticed that a let(:name)-declaration in my spec was being called from ActiveRecord::TestFixtures#run_in_transaction? which is AFAIU supposed to call RSpec::Rails::FixtureSupport::Fixtures#name instead.
Expected behaviour
I’d want to be warned if I’m redefining a reserved method via RSpec::Core::MemoizedHelpers#let similar to how initialize is a reserved keyword.
Can you provide an example app?
Start with a blank rails app (Version => 6.1):
gem install rails -v '6.1.1'
rails new rspec-rails-issue
Install rspec-rails (Version >= 4.0.2):
group :development, :test do
gem 'rspec-rails', '~> 4.0.2'
end
Install RSpec:
rails generate rspec:install
Create spec/some_spec.rb:
require 'rails_helper'
RSpec.describe "observes a call to :name" do
subject { true }
let(:name) { puts caller; puts "I should never have been called" }
it { is_expected.to be_truthy }
end
Run the spec:
rspec spec/some_spec.rb
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:317:in `block (2 levels) in let'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:157:in `block (3 levels) in fetch_or_store'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:157:in `fetch'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:157:in `block (2 levels) in fetch_or_store'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-support-3.10.2/lib/rspec/support/reentrant_mutex.rb:23:in `synchronize'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:156:in `block in fetch_or_store'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:155:in `fetch'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:155:in `fetch_or_store'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/memoized_helpers.rb:317:in `block in let'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/activerecord-6.1.1/lib/active_record/test_fixtures.rb:102:in `run_in_transaction?'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/activerecord-6.1.1/lib/active_record/test_fixtures.rb:116:in `setup_fixtures'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/activerecord-6.1.1/lib/active_record/test_fixtures.rb:10:in `before_setup'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-rails-4.0.2/lib/rspec/rails/adapters.rb:74:in `block (2 levels) in <module:MinitestLifecycleAdapter>'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:455:in `instance_exec'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:455:in `instance_exec'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:390:in `execute_with'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:628:in `block (2 levels) in run_around_example_hooks_for'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:350:in `call'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:629:in `run_around_example_hooks_for'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/hooks.rb:486:in `run'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:465:in `with_around_example_hooks'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:508:in `with_around_and_singleton_context_hooks'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example.rb:259:in `run'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:644:in `block in run_examples'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:640:in `map'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:640:in `run_examples'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/example_group.rb:606:in `run'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:121:in `block (3 levels) in run_specs'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:121:in `map'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:121:in `block (2 levels) in run_specs'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/configuration.rb:2067:in `with_suite_hooks'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:116:in `block in run_specs'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/reporter.rb:74:in `report'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:115:in `run_specs'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:89:in `run'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:71:in `run'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/lib/rspec/core/runner.rb:45:in `invoke'
[…path omitted]/.asdf/installs/ruby/2.7.1/lib/ruby/gems/2.7.0/gems/rspec-core-3.10.1/exe/rspec:4:in `<top (required)>'
[…path omitted]/.asdf/installs/ruby/2.7.1/bin/rspec:23:in `load'
[…path omitted]/.asdf/installs/ruby/2.7.1/bin/rspec:23:in `<main>'
I should never have been called
.
Finished in 0.02096 seconds (files took 1.89 seconds to load)
1 example, 0 failures
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 15 (8 by maintainers)
Commits related to this issue
- Avoid a bug of rails 6.1 cf. https://github.com/rspec/rspec-rails/issues/2451 — committed to sankichi92/LiveLog by sankichi92 3 years ago
- Bump rails from 6.0.3.4 to 6.1.1 (#1181) * Bump rails from 6.0.3.4 to 6.1.1 Bumps [rails](https://github.com/rails/rails) from 6.0.3.4 to 6.1.1. - [Release notes](https://github.com/rails/rails/r... — committed to sankichi92/LiveLog by dependabot-preview[bot] 3 years ago
- Prevent collision on :name and :method_name in rspec-rails examples Fix: https://github.com/rspec/rspec-rails/issues/2451 — committed to rspec/rspec-rails by benoittgt 3 years ago
- Prevent collisions on let :name and :method_name in rspec-rails examples Fix: https://github.com/rspec/rspec-rails/issues/2451 — committed to rspec/rspec-rails by benoittgt 3 years ago
- Prevent collisions on let :name and :method_name in rspec-rails examples Fix: https://github.com/rspec/rspec-rails/issues/2451 — committed to rspec/rspec-rails by benoittgt 3 years ago
My theory is it’s a very, very old relic - entered with f3de931145ea7143aef2e109eeba7e9d1ec79f4e, but irrelevant in rspec-core since
d941ba7. I haven’t seen what happens to tests if it gets removed/changed, though.@pirj I do use the branch now. the patch I mentioned needs it to work 🙂 but just using the branch doesn’t solve the issue, unfortunately.
This is an excellent representation of what I was seeing in #2417 (comment here). Like @grekko said above, it seems like the fundamental issue is the ActiveSupport method
run_in_transaction?(changed between Rails 6.0 and 6.1), which is run in the example namespace, callingname; anylet(:name)will override the method inRSpec::Rails::FixtureSupport:I wanted to verify that https://github.com/rspec/rspec-rails/pull/2423 would fix the issue I described, so I adjusted the setup from the PR description:
What I changed
I replaced the reference to rspec
4.0.2withrails-6-1-dev:… and rerunning the spec above displays the same behaviour:
Please use the unreleased version in
rails-6-1-devthere is a fix for this. (Closed as duplicate of #2417)