Skip to content

Commit 0ce6bef

Browse files
committed
feat: log a warning when too many interactions are set on the mock service at once
1 parent 4d60726 commit 0ce6bef

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

lib/pact/mock_service/app.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ def self.new *args
1515
end
1616

1717
class App
18-
1918
def initialize options = {}
2019
logger = Logger.from_options(options)
20+
stubbing = options[:stub_pactfile_paths] && options[:stub_pactfile_paths].any?
2121
@name = options.fetch(:name, "MockService")
22-
@session = Session.new(options.merge(logger: logger))
23-
setup_stub(options[:stub_pactfile_paths]) if options[:stub_pactfile_paths]
22+
@session = Session.new(options.merge(logger: logger, warn_on_too_many_interactions: !stubbing))
23+
setup_stub(options[:stub_pactfile_paths]) if stubbing
2424
request_handlers = RequestHandlers.new(@name, logger, @session, options)
2525
@app = Rack::Builder.app do
2626
use Pact::Consumer::MockService::ErrorHandler, logger

lib/pact/mock_service/session.rb

+10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ def initialize options
1717
@expected_interactions = Interactions::ExpectedInteractions.new
1818
@actual_interactions = Interactions::ActualInteractions.new
1919
@verified_interactions = Interactions::VerifiedInteractions.new
20+
@warn_on_too_many_interactions = options[:warn_on_too_many_interactions] || false
21+
@max_concurrent_interactions_before_warning = get_max_concurrent_interactions_before_warning
2022
@consumer_contract_details = {
2123
pact_dir: options[:pact_dir],
2224
consumer: {name: options[:consumer]},
@@ -64,10 +66,15 @@ def add_expected_interaction interaction
6466

6567
private
6668

69+
attr_reader :warn_on_too_many_interactions, :max_concurrent_interactions_before_warning
70+
6771
def really_add_expected_interaction interaction
6872
expected_interactions << interaction
6973
logger.info "Registered expected interaction #{interaction.request.method_and_path}"
7074
logger.debug JSON.pretty_generate InteractionDecorator.new(interaction)
75+
if warn_on_too_many_interactions && expected_interactions.size > max_concurrent_interactions_before_warning
76+
logger.warn "You currently have #{expected_interactions.size} interactions mocked at the same time. This suggests the scope of your consumer tests is larger than recommended, and you may find them hard to debug and maintain. See https://pact.io/too-many-interactions for more information."
77+
end
7178
end
7279

7380
def handle_almost_duplicate_interaction previous_interaction, interaction
@@ -81,6 +88,9 @@ def interaction_already_verified_with_same_description_and_provider_state_but_no
8188
other && other != interaction ? other : nil
8289
end
8390

91+
def get_max_concurrent_interactions_before_warning
92+
ENV['PACT_MAX_CONCURRENT_INTERACTIONS_BEFORE_WARNING'] ? ENV['PACT_MAX_CONCURRENT_INTERACTIONS_BEFORE_WARNING'].to_i : 3
93+
end
8494
end
8595
end
8696
end

spec/lib/pact/mock_service/session_spec.rb

+26-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ module Pact::MockService
77
let(:logger) { double('Logger').as_null_object }
88

99
describe "set_expected_interactions" do
10-
1110
let(:interaction_1) { InteractionFactory.create }
1211
let(:interaction_2) { InteractionFactory.create }
1312
let(:interactions) { [interaction_1, interaction_2] }
@@ -84,6 +83,7 @@ module Pact::MockService
8483
let(:expected_interactions) { instance_double('Interactions::ExpectedInteractions', :<< => nil) }
8584
let(:actual_interactions) { instance_double('Interactions::ActualInteractions') }
8685
let(:verified_interactions) { instance_double('Interactions::VerifiedInteractions') }
86+
let(:matching_interaction) { nil }
8787

8888
before do
8989
allow(Interactions::ExpectedInteractions).to receive(:new).and_return(expected_interactions)
@@ -95,8 +95,6 @@ module Pact::MockService
9595
subject { Session.new(logger: logger) }
9696

9797
context "when there is no already verified interaction with the same description and provider state" do
98-
let(:matching_interaction) { nil }
99-
10098
it "adds the new interaction to the interaction list" do
10199
expect(expected_interactions).to receive(:<<).with(interaction_1)
102100
subject.add_expected_interaction interaction_1
@@ -138,6 +136,31 @@ module Pact::MockService
138136
expect { subject.add_expected_interaction interaction_1 }.to raise_error SameSameButDifferentError, diff_message
139137
end
140138
end
139+
140+
context "when there are more than 3 interactions mocked at the same time" do
141+
subject { Session.new(logger: logger, warn_on_too_many_interactions: true) }
142+
143+
it "logs a warning" do
144+
allow(expected_interactions).to receive(:size).and_return(3, 4)
145+
expect(logger).to receive(:warn).with(/You currently have 4 interactions/).once
146+
subject.add_expected_interaction(InteractionFactory.create('description' => 'third interaction')) # no warning
147+
subject.add_expected_interaction(InteractionFactory.create('description' => 'forth interaction')) # warning
148+
end
149+
150+
context "when PACT_MAX_CONCURRENT_INTERACTIONS_BEFORE_WARNING is set" do
151+
before do
152+
allow(ENV).to receive(:[]).and_call_original
153+
allow(ENV).to receive(:[]).with("PACT_MAX_CONCURRENT_INTERACTIONS_BEFORE_WARNING").and_return("5")
154+
end
155+
156+
it "logs a warning when over the configured limit" do
157+
allow(expected_interactions).to receive(:size).and_return(5, 6)
158+
expect(logger).to receive(:warn).with(/You currently have 6 interactions/).once
159+
subject.add_expected_interaction(InteractionFactory.create('description' => 'fifth interaction')) # no warning
160+
subject.add_expected_interaction(InteractionFactory.create('description' => 'sixth interaction')) # warning
161+
end
162+
end
163+
end
141164
end
142165
end
143166
end

0 commit comments

Comments
 (0)