Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit 6fa443f

Browse files
committed
Stash methods that get and set thread local variables to allow the user to mock them
Fixes #605.
1 parent 42b18c4 commit 6fa443f

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

lib/rspec/support.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,23 @@ def self.class_of(object)
9090
singleton_class.ancestors.find { |ancestor| !ancestor.equal?(singleton_class) }
9191
end
9292

93-
# A single thread local variable so we don't excessively pollute that namespace.
93+
# Stash original methods to allow the user to mock them.
9494
if RUBY_VERSION.to_f >= 2
95+
THREAD_VARIABLE_GET = Thread.instance_method(:thread_variable_get)
96+
THREAD_VARIABLE_SET = Thread.instance_method(:thread_variable_set)
97+
else
98+
THREAD_VARIABLE_GET = Thread.instance_method(:[])
99+
THREAD_VARIABLE_SET = Thread.instance_method(:[]=)
100+
end
101+
102+
# A single thread local variable so we don't excessively pollute that namespace.
103+
if RUBY_VERSION >= '2.7'
95104
def self.thread_local_data
96-
Thread.current.thread_variable_get(:__rspec) || Thread.current.thread_variable_set(:__rspec, {})
105+
THREAD_VARIABLE_GET.bind_call(Thread.current, :__rspec) || THREAD_VARIABLE_SET.bind_call(Thread.current, :__rspec, {})
97106
end
98107
else
99108
def self.thread_local_data
100-
Thread.current[:__rspec] ||= {}
109+
THREAD_VARIABLE_GET.bind(Thread.current).call(:__rspec) || THREAD_VARIABLE_SET.bind(Thread.current).call(:__rspec, {})
101110
end
102111
end
103112

spec/rspec/support_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,17 @@ def object.some_method
204204
end.resume
205205
end
206206
end
207+
208+
it "works when Thread#thread_variable_get and Thread#thread_variable_set are mocked" do
209+
expect(Thread.current).to receive(:thread_variable_set).with(:test, true).once.and_return(true)
210+
expect(Thread.current).to receive(:thread_variable_get).with(:test).once.and_return(true)
211+
212+
Thread.current.thread_variable_set(:test, true)
213+
expect(Thread.current.thread_variable_get(:test)).to eq true
214+
215+
RSpec::Support.thread_local_data[:__for_test] = :oh_hai
216+
expect(RSpec::Support.thread_local_data[:__for_test]).to eq :oh_hai
217+
end
207218
end
208219

209220
describe "failure notification" do

0 commit comments

Comments
 (0)