Skip to content

RSpec does not reset ActiveSupport::CurrentAttributes around each example #2503

Closed
@mattbrictson

Description

@mattbrictson

What Ruby, Rails and RSpec versions are you using?

Ruby version: ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin20]
Rails version: 6.1.3.2
RSpec version: RSpec 3.10

  • rspec-core 3.10.1
  • rspec-expectations 3.10.1
  • rspec-mocks 3.10.2
  • rspec-rails 5.0.1
  • rspec-support 3.10.2

Observed behaviour

rspec-rails does not reset CurrentAttributes. That means if one test sets a value using CurrentAttributes, it can very easily pollute other tests.

Expected behaviour

Rails ActiveSupport::TestCase automatically resets CurrentAttributes between each test (see active_support/current_attributes/test_helper.rb). I would expect rspec-rails to do the same.

Can you provide an example app?

Here is a trivial example app using CurrentAttributes and an ActiveSupport::TestCase that passes:

require "rails"
require "rails/test_help"

class MyApp < Rails::Application
  config.eager_load = false
end

MyApp.initialize!

class Current < ActiveSupport::CurrentAttributes
  attribute :user_id
end

class CurrentTest < ActiveSupport::TestCase
  test "allows setting user_id" do
    Current.user_id = 123
    assert_equal(123, Current.user_id)
  end

  test "has a nil user_id by default" do
    assert_nil(Current.user_id)
  end
end

Test output:

$ bundle exec ruby testcase.rb 
Run options: --seed 52779

# Running:

..

Finished in 0.001012s, 1976.2846 runs/s, 1976.2846 assertions/s.
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips

However the same app, when tested via rspec-rails, fails:

require "rails"
require "action_controller/railtie"
require "action_view/railtie"
require "rspec/rails"

class MyApp < Rails::Application
  config.eager_load = false
end

MyApp.initialize!

class Current < ActiveSupport::CurrentAttributes
  attribute :user_id
end

describe Current do
  it "allows setting user_id" do
    Current.user_id = 123
    expect(Current.user_id).to eq(123)
  end

  it "has a nil user_id by default" do
    expect(Current.user_id).to be_nil
  end
end

Spec output:

$ bundle exec rspec rspec.rb 
.F

Failures:

  1) Current has a nil user_id by default
     Failure/Error: expect(Current.user_id).to be_nil
     
       expected: nil
            got: 123
     # ./rspec.rb:23:in `block (2 levels) in <top (required)>'

Finished in 0.01094 seconds (files took 0.66551 seconds to load)
2 examples, 1 failure

Failed examples:

rspec ./rspec.rb:22 # Current has a nil user_id by default

Here is the Gemfile I used:

source "https://rubygems.org"

gem "rails", "~> 6.1"
gem "rspec", "~> 3.10"
gem "rspec-rails", "~> 5.0"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions