DEV: Use rspec mocks to properly verify a race condition

This is a small followup of https://github.com/discourse/discourse/pull/28124.
This commit is contained in:
Loïc Guitaut 2024-07-31 10:12:54 +02:00 committed by Loïc Guitaut
parent 6f80ebfc41
commit 9e9d88f078
4 changed files with 34 additions and 8 deletions

View File

@ -158,6 +158,8 @@ group :test, :development do
gem "syntax_tree"
gem "syntax_tree-disable_ternary"
gem "rspec-multi-mock"
end
group :development do

View File

@ -426,6 +426,8 @@ GEM
rspec-mocks (3.13.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-multi-mock (0.3.1)
rspec (>= 3.7.0)
rspec-rails (6.1.3)
actionpack (>= 6.1)
activesupport (>= 6.1)
@ -699,6 +701,7 @@ DEPENDENCIES
rrule
rspec
rspec-html-matchers
rspec-multi-mock
rspec-rails
rss
rswag-specs

View File

@ -122,14 +122,16 @@ RSpec.describe Cache do
end
end
it "isn't prone to a race condition due to key expiring between GET calls" do
key = cache.normalize_key("my_key")
context "when there is a race condition due to key expiring between GET calls" do
before do
allow(Discourse.redis).to receive(:get).and_wrap_original do |original_method, *args|
original_method.call(*args).tap { Discourse.redis.del(*args) }
end
end
# while this is not technically testing the race condition, it's
# ensuring we're only calling redis.get once, which is a good enough proxy
Discourse.redis.stubs(:get).with(key).returns(Marshal.dump("bob")).once
expect(fetch_value).to eq("bob")
it "isn't prone to that race condition" do
expect(fetch_value).to eq("bob")
end
end
end
end

View File

@ -186,7 +186,18 @@ end
PER_SPEC_TIMEOUT_SECONDS = 45
BROWSER_READ_TIMEOUT = 30
# To avoid erasing `any_instance` from Mocha
require "rspec/mocks/syntax"
RSpec::Mocks::Syntax.singleton_class.define_method(:enable_should) { |*| nil }
RSpec::Mocks::Syntax.singleton_class.define_method(:disable_should) { |*| nil }
RSpec::Mocks::ArgumentMatchers.remove_method(:hash_including) # Were currently relying on the version from Webmock
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = :expect
end
config.fail_fast = ENV["RSPEC_FAIL_FAST"] == "1"
config.silence_filter_announcements = ENV["RSPEC_SILENCE_FILTER_ANNOUNCEMENTS"] == "1"
config.extend RedisSnapshotHelper
@ -206,10 +217,18 @@ RSpec.configure do |config|
config.include ServiceMatchers
config.include I18nHelpers
config.mock_framework = :mocha
config.order = "random"
config.infer_spec_type_from_file_location!
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
mocks.verify_doubled_constant_names = true
mocks.syntax = :expect
end
config.mock_with MultiMock::Adapter.for(:mocha, :rspec)
config.include Mocha::API
if ENV["GITHUB_ACTIONS"]
# Enable color output in GitHub Actions
# This eventually will be `config.color_mode = :on` in RSpec 4?