Created
July 12, 2022 19:14
-
-
Save JoshCheek/baa4ed3829b43d0e995a6afc5aa57792 to your computer and use it in GitHub Desktop.
Example how how stubbing methods could be threadsafe (IDK if this is how RSpec does it or not)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# really rudimentary stubbing mechanism (eg doesn't support unstubbing) | |
def stub(obj, method, *expected, result) | |
Thread.current[:stubs] ||= {} | |
Thread.current[:stubs][method] ||= {} | |
Thread.current[:stubs][method][expected] = result | |
obj.define_singleton_method method do |*actual| # we'll ignore keyword args here for simplicity | |
Thread.current[:stubs][method].fetch(actual) do | |
raise "#{method} invoked with unexpected args: #{actual.inspect}" | |
end | |
end | |
end | |
t1 = t2 = nil | |
t1 = Thread.new do | |
Thread.current.abort_on_exception = true | |
stub ENV, :[], 'KEY', "value from line #{__LINE__}" | |
puts "THREAD1: ENV['KEY'] = #{ENV['KEY'].inspect}" | |
Thread.pass until t2.stop? | |
t2.run | |
sleep | |
puts "THREAD1: ENV['KEY'] = #{ENV['KEY'].inspect}" | |
Thread.pass until t2.stop? | |
t2.run | |
end | |
t2 = Thread.new do | |
Thread.current.abort_on_exception = true | |
stub ENV, :[], 'KEY', "value from line #{__LINE__}" | |
sleep | |
puts "THREAD2: ENV['KEY'] = #{ENV['KEY'].inspect}" | |
Thread.pass until t1.stop? | |
t1.run | |
sleep | |
puts "THREAD2: ENV['KEY'] = #{ENV['KEY'].inspect}" | |
end | |
t1.run | |
[t1, t2].each &:join | |
# >> THREAD1: ENV['KEY'] = "value from line 17" | |
# >> THREAD2: ENV['KEY'] = "value from line 29" | |
# >> THREAD1: ENV['KEY'] = "value from line 17" | |
# >> THREAD2: ENV['KEY'] = "value from line 29" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment