diff --git a/lib/rspec/support.rb b/lib/rspec/support.rb index 72154e07..57f310e5 100644 --- a/lib/rspec/support.rb +++ b/lib/rspec/support.rb @@ -90,14 +90,23 @@ def self.class_of(object) singleton_class.ancestors.find { |ancestor| !ancestor.equal?(singleton_class) } end - # A single thread local variable so we don't excessively pollute that namespace. + # Stash original methods to allow the user to mock them. if RUBY_VERSION.to_f >= 2 + THREAD_VARIABLE_GET = Thread.instance_method(:thread_variable_get) + THREAD_VARIABLE_SET = Thread.instance_method(:thread_variable_set) + else + THREAD_VARIABLE_GET = Thread.instance_method(:[]) + THREAD_VARIABLE_SET = Thread.instance_method(:[]=) + end + + # A single thread local variable so we don't excessively pollute that namespace. + if RUBY_VERSION >= '2.7' def self.thread_local_data - Thread.current.thread_variable_get(:__rspec) || Thread.current.thread_variable_set(:__rspec, {}) + THREAD_VARIABLE_GET.bind_call(Thread.current, :__rspec) || THREAD_VARIABLE_SET.bind_call(Thread.current, :__rspec, {}) end else def self.thread_local_data - Thread.current[:__rspec] ||= {} + THREAD_VARIABLE_GET.bind(Thread.current).call(:__rspec) || THREAD_VARIABLE_SET.bind(Thread.current).call(:__rspec, {}) end end diff --git a/spec/rspec/support_spec.rb b/spec/rspec/support_spec.rb index 75d784dd..a40dc718 100644 --- a/spec/rspec/support_spec.rb +++ b/spec/rspec/support_spec.rb @@ -204,6 +204,17 @@ def object.some_method end.resume end end + + it "works when Thread#thread_variable_get and Thread#thread_variable_set are mocked" do + expect(Thread.current).to receive(:thread_variable_set).with(:test, true).once.and_return(true) + expect(Thread.current).to receive(:thread_variable_get).with(:test).once.and_return(true) + + Thread.current.thread_variable_set(:test, true) + expect(Thread.current.thread_variable_get(:test)).to eq true + + RSpec::Support.thread_local_data[:__for_test] = :oh_hai + expect(RSpec::Support.thread_local_data[:__for_test]).to eq :oh_hai + end end describe "failure notification" do