pact 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +20 -0
- data/Gemfile.lock +3 -3
- data/example/animal-service/Gemfile +14 -0
- data/example/animal-service/Gemfile.lock +67 -0
- data/example/animal-service/Rakefile +3 -0
- data/example/animal-service/spec/service_consumers/pact_helper.rb +24 -0
- data/example/animal-service/spec/service_consumers/provider_states_for_zoo_app.rb +9 -0
- data/example/zoo-app/Gemfile.lock +2 -15
- data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +21 -6
- data/example/zoo-app/spec/service_providers/animal_service_spec.rb +1 -1
- data/lib/pact/consumer.rb +10 -11
- data/lib/pact/consumer/app_manager.rb +1 -0
- data/lib/pact/consumer/configuration.rb +179 -0
- data/lib/pact/consumer/interaction_builder.rb +1 -2
- data/lib/pact/consumer/mock_service.rb +1 -370
- data/lib/pact/consumer/mock_service/app.rb +70 -0
- data/lib/pact/consumer/mock_service/interaction_delete.rb +28 -0
- data/lib/pact/consumer/mock_service/interaction_list.rb +57 -0
- data/lib/pact/consumer/mock_service/interaction_post.rb +25 -0
- data/lib/pact/consumer/mock_service/interaction_replay.rb +126 -0
- data/lib/pact/consumer/mock_service/missing_interactions_get.rb +26 -0
- data/lib/pact/consumer/mock_service/rack_request_helper.rb +51 -0
- data/lib/pact/consumer/mock_service/startup_poll.rb +22 -0
- data/lib/pact/consumer/mock_service/verification_get.rb +35 -0
- data/lib/pact/consumer/mock_service_client.rb +3 -1
- data/lib/pact/consumer/mock_service_interaction_expectation.rb +33 -0
- data/lib/pact/consumer/request.rb +27 -0
- data/lib/pact/consumer/rspec.rb +1 -4
- data/lib/pact/consumer_contract/consumer_contract.rb +11 -8
- data/lib/pact/consumer_contract/interaction.rb +9 -22
- data/lib/pact/consumer_contract/request.rb +68 -0
- data/lib/pact/consumer_contract/service_consumer.rb +6 -2
- data/lib/pact/consumer_contract/service_provider.rb +6 -2
- data/lib/pact/matchers/index_not_found.rb +20 -0
- data/lib/pact/matchers/matchers.rb +14 -28
- data/lib/pact/matchers/unexpected_index.rb +17 -0
- data/lib/pact/matchers/unexpected_key.rb +17 -0
- data/lib/pact/provider.rb +1 -1
- data/lib/pact/provider/configuration.rb +129 -0
- data/lib/pact/provider/request.rb +59 -0
- data/lib/pact/provider/rspec.rb +4 -5
- data/lib/pact/provider/test_methods.rb +14 -52
- data/lib/pact/shared/dsl.rb +20 -0
- data/lib/pact/shared/key_not_found.rb +24 -0
- data/lib/pact/shared/null_expectation.rb +31 -0
- data/lib/pact/shared/request.rb +68 -0
- data/lib/pact/something_like.rb +7 -1
- data/lib/pact/symbolize_keys.rb +12 -0
- data/lib/pact/tasks.rb +1 -1
- data/lib/pact/tasks/task_helper.rb +23 -0
- data/lib/pact/{verification_task.rb → tasks/verification_task.rb} +4 -4
- data/lib/pact/version.rb +1 -1
- data/lib/tasks/pact.rake +5 -4
- data/pact.gemspec +1 -1
- data/spec/features/consumption_spec.rb +1 -73
- data/spec/features/production_spec.rb +3 -0
- data/spec/integration/consumer_spec.rb +170 -0
- data/spec/integration/pact/consumer_configuration_spec.rb +1 -1
- data/spec/lib/pact/consumer/{dsl_spec.rb → configuration_spec.rb} +10 -9
- data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +2 -2
- data/spec/lib/pact/consumer/interaction_builder_spec.rb +1 -1
- data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +66 -0
- data/spec/lib/pact/consumer/mock_service/rack_request_helper_spec.rb +82 -0
- data/spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb +54 -0
- data/spec/lib/pact/consumer/request_spec.rb +24 -0
- data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +1 -1
- data/spec/lib/pact/consumer_contract/interaction_spec.rb +0 -34
- data/spec/lib/pact/{request_spec.rb → consumer_contract/request_spec.rb} +45 -121
- data/spec/lib/pact/matchers/matchers_spec.rb +29 -13
- data/spec/lib/pact/provider/configuration_spec.rb +163 -0
- data/spec/lib/pact/provider/request_spec.rb +78 -0
- data/spec/lib/pact/provider/test_methods_spec.rb +0 -30
- data/spec/lib/pact/verification_task_spec.rb +1 -1
- data/spec/spec_helper.rb +3 -0
- data/spec/support/factories.rb +5 -1
- data/spec/support/pact_helper.rb +6 -0
- data/spec/support/shared_examples_for_request.rb +83 -0
- data/spec/support/test_app_fail.json +3 -0
- data/spec/support/test_app_pass.json +18 -1
- metadata +68 -31
- data/lib/pact/consumer/dsl.rb +0 -157
- data/lib/pact/pact_task_helper.rb +0 -21
- data/lib/pact/provider/dsl.rb +0 -115
- data/lib/pact/request.rb +0 -167
- data/spec/lib/pact/consumer/mock_service_spec.rb +0 -143
- data/spec/lib/pact/provider/dsl_spec.rb +0 -179
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'pact/reification'
|
3
|
-
require 'pact/request'
|
4
3
|
require 'pact/consumer_contract/interaction'
|
5
4
|
|
6
5
|
module Pact
|
@@ -24,7 +23,7 @@ module Pact
|
|
24
23
|
end
|
25
24
|
|
26
25
|
def with(request_details)
|
27
|
-
interaction.request = Request::Expected.from_hash(request_details)
|
26
|
+
interaction.request = Pact::Request::Expected.from_hash(request_details)
|
28
27
|
self
|
29
28
|
end
|
30
29
|
|
@@ -1,371 +1,2 @@
|
|
1
|
-
require '
|
2
|
-
require 'uri'
|
3
|
-
require 'json'
|
4
|
-
require 'hashie'
|
5
|
-
require 'singleton'
|
6
|
-
require 'logger'
|
7
|
-
require 'awesome_print'
|
8
|
-
require 'awesome_print/core_ext/logger' #For some reason we get an error indicating that the method 'ap' is private unless we load this specifically
|
9
|
-
require 'json/add/regexp'
|
10
|
-
require 'pact/matchers'
|
1
|
+
require 'pact/consumer/mock_service/app'
|
11
2
|
|
12
|
-
AwesomePrint.defaults = {
|
13
|
-
indent: -2,
|
14
|
-
plain: true,
|
15
|
-
index: false
|
16
|
-
}
|
17
|
-
|
18
|
-
module Pact
|
19
|
-
module Consumer
|
20
|
-
|
21
|
-
class InteractionList
|
22
|
-
#include Singleton
|
23
|
-
|
24
|
-
attr_reader :interactions
|
25
|
-
attr_reader :unexpected_requests
|
26
|
-
|
27
|
-
def initialize
|
28
|
-
clear
|
29
|
-
end
|
30
|
-
|
31
|
-
# For testing, sigh
|
32
|
-
def clear
|
33
|
-
@interactions = []
|
34
|
-
@matched_interactions = []
|
35
|
-
@unexpected_requests = []
|
36
|
-
end
|
37
|
-
|
38
|
-
def add interactions
|
39
|
-
@interactions << interactions
|
40
|
-
end
|
41
|
-
|
42
|
-
def register_matched interaction
|
43
|
-
@matched_interactions << interaction
|
44
|
-
end
|
45
|
-
|
46
|
-
# Request::Actual
|
47
|
-
def register_unexpected request
|
48
|
-
@unexpected_requests << request
|
49
|
-
end
|
50
|
-
|
51
|
-
def all_matched?
|
52
|
-
interaction_diffs.empty?
|
53
|
-
end
|
54
|
-
|
55
|
-
def missing_interactions
|
56
|
-
@interactions - @matched_interactions
|
57
|
-
end
|
58
|
-
|
59
|
-
def interaction_diffs
|
60
|
-
{
|
61
|
-
:missing_interactions => missing_interactions,
|
62
|
-
:unexpected_requests => unexpected_requests.collect(&:as_json)
|
63
|
-
}.inject({}) do | hash, pair |
|
64
|
-
hash[pair.first] = pair.last if pair.last.any?
|
65
|
-
hash
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
module RackHelper
|
72
|
-
def params_hash env
|
73
|
-
env["QUERY_STRING"].split("&").collect{| param| param.split("=")}.inject({}){|params, param| params[param.first] = URI.decode(param.last); params }
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
class StartupPoll
|
78
|
-
|
79
|
-
def initialize name, logger
|
80
|
-
@name = name
|
81
|
-
@logger = logger
|
82
|
-
end
|
83
|
-
|
84
|
-
def match? env
|
85
|
-
env['REQUEST_PATH'] == '/index.html' &&
|
86
|
-
env['REQUEST_METHOD'] == 'GET'
|
87
|
-
end
|
88
|
-
|
89
|
-
def respond env
|
90
|
-
@logger.info "#{@name} started up"
|
91
|
-
[200, {}, ['Started up fine']]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
class CapybaraIdentify
|
96
|
-
|
97
|
-
def initialize name, logger
|
98
|
-
@name = name
|
99
|
-
@logger = logger
|
100
|
-
end
|
101
|
-
|
102
|
-
def match? env
|
103
|
-
env["PATH_INFO"] == "/__identify__"
|
104
|
-
end
|
105
|
-
|
106
|
-
def respond env
|
107
|
-
[200, {}, [object_id.to_s]]
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
class InteractionDelete
|
112
|
-
|
113
|
-
include RackHelper
|
114
|
-
|
115
|
-
def initialize name, logger, interaction_list
|
116
|
-
@name = name
|
117
|
-
@logger = logger
|
118
|
-
@interaction_list = interaction_list
|
119
|
-
end
|
120
|
-
|
121
|
-
def match? env
|
122
|
-
env['REQUEST_PATH'].start_with?('/interactions') &&
|
123
|
-
env['REQUEST_METHOD'] == 'DELETE'
|
124
|
-
end
|
125
|
-
|
126
|
-
def respond env
|
127
|
-
@interaction_list.clear
|
128
|
-
@logger.info "Cleared interactions before example \"#{params_hash(env)['example_description']}\""
|
129
|
-
[200, {}, ['Deleted interactions']]
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
class InteractionPost
|
134
|
-
|
135
|
-
def initialize name, logger, interaction_list
|
136
|
-
@name = name
|
137
|
-
@logger = logger
|
138
|
-
@interaction_list = interaction_list
|
139
|
-
end
|
140
|
-
|
141
|
-
def match? env
|
142
|
-
env['REQUEST_PATH'] == '/interactions' &&
|
143
|
-
env['REQUEST_METHOD'] == 'POST'
|
144
|
-
end
|
145
|
-
|
146
|
-
def respond env
|
147
|
-
interactions = Hashie::Mash.new(JSON.load(env['rack.input'].string))
|
148
|
-
@interaction_list.add interactions
|
149
|
-
@logger.info "Added interaction to #{@name}"
|
150
|
-
@logger.ap interactions
|
151
|
-
[200, {}, ['Added interactions']]
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
module RequestExtractor
|
156
|
-
|
157
|
-
REQUEST_KEYS = Hashie::Mash.new({
|
158
|
-
'REQUEST_METHOD' => :method,
|
159
|
-
'REQUEST_PATH' => :path,
|
160
|
-
'QUERY_STRING' => :query,
|
161
|
-
'rack.input' => :body
|
162
|
-
})
|
163
|
-
|
164
|
-
def request_from env
|
165
|
-
request = env.inject({}) do |memo, (k, v)|
|
166
|
-
request_key = REQUEST_KEYS[k]
|
167
|
-
memo[request_key] = v if request_key
|
168
|
-
memo
|
169
|
-
end
|
170
|
-
|
171
|
-
mashed_request = Hashie::Mash.new request
|
172
|
-
mashed_request[:headers] = headers_from env
|
173
|
-
body_string = mashed_request[:body].read
|
174
|
-
|
175
|
-
if body_string.empty?
|
176
|
-
mashed_request.delete :body
|
177
|
-
else
|
178
|
-
body_is_json = mashed_request[:headers]['Content-Type'] =~ /json/
|
179
|
-
mashed_request[:body] = body_is_json ? JSON.parse(body_string) : body_string
|
180
|
-
end
|
181
|
-
mashed_request[:method] = mashed_request[:method].downcase
|
182
|
-
mashed_request
|
183
|
-
end
|
184
|
-
|
185
|
-
def headers_from env
|
186
|
-
headers = env.reject{ |key, value| !(key.start_with?("HTTP") || key == 'CONTENT_TYPE')}
|
187
|
-
headers.inject({}) do | hash, header |
|
188
|
-
hash[standardise_header(header.first)] = header.last
|
189
|
-
hash
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def standardise_header header
|
194
|
-
header.gsub(/^HTTP_/, '').split("_").collect{|word| word[0] + word[1..-1].downcase}.join("-")
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
class InteractionReplay
|
199
|
-
include Pact::Matchers
|
200
|
-
include RequestExtractor
|
201
|
-
|
202
|
-
def initialize name, logger, interaction_list
|
203
|
-
@name = name
|
204
|
-
@logger = logger
|
205
|
-
@interaction_list = interaction_list
|
206
|
-
end
|
207
|
-
|
208
|
-
def match? env
|
209
|
-
true # default handler
|
210
|
-
end
|
211
|
-
|
212
|
-
def respond env
|
213
|
-
find_response request_from(env)
|
214
|
-
end
|
215
|
-
|
216
|
-
private
|
217
|
-
|
218
|
-
def find_response raw_request
|
219
|
-
actual_request = Request::Actual.from_hash(raw_request)
|
220
|
-
@logger.info "#{@name} received request"
|
221
|
-
@logger.ap actual_request.as_json
|
222
|
-
candidates = []
|
223
|
-
matching_interactions = @interaction_list.interactions.select do |interaction|
|
224
|
-
expected_request = Request::Expected.from_hash(interaction.request.merge(:description => interaction.description))
|
225
|
-
candidates << expected_request if expected_request.matches_route? actual_request
|
226
|
-
expected_request.match actual_request
|
227
|
-
end
|
228
|
-
if matching_interactions.size > 1
|
229
|
-
@logger.error "Multiple interactions found on #{@name}:"
|
230
|
-
@logger.ap matching_interactions
|
231
|
-
raise "Multiple interactions found for path #{actual_request.path}!"
|
232
|
-
end
|
233
|
-
if matching_interactions.empty?
|
234
|
-
handle_unrecognised_request(actual_request, candidates)
|
235
|
-
else
|
236
|
-
response = response_from(matching_interactions.first.response)
|
237
|
-
@interaction_list.register_matched matching_interactions.first
|
238
|
-
@logger.info "Found matching response on #{@name}:"
|
239
|
-
@logger.ap response
|
240
|
-
response
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
def handle_unrecognised_request request, candidates
|
245
|
-
@interaction_list.register_unexpected request
|
246
|
-
@logger.error "No interaction found on #{@name} amongst expected requests \"#{candidates.map(&:description).join(', ')}\""
|
247
|
-
@logger.error 'Interaction diffs for that route:'
|
248
|
-
interaction_diff = candidates.map do |candidate|
|
249
|
-
candidate.difference(request)
|
250
|
-
end.to_a
|
251
|
-
@logger.ap(interaction_diff, :error)
|
252
|
-
response = {message: "No interaction found for #{request.path}", interaction_diff: interaction_diff}
|
253
|
-
[500, {'Content-Type' => 'application/json'}, [response.to_json]]
|
254
|
-
end
|
255
|
-
|
256
|
-
def response_from response
|
257
|
-
[response.status, (response.headers || {}).to_hash, [render_body(response.body)]]
|
258
|
-
end
|
259
|
-
|
260
|
-
def render_body body
|
261
|
-
return '' unless body
|
262
|
-
body.kind_of?(String) ? body.force_encoding('utf-8') : body.to_json
|
263
|
-
end
|
264
|
-
|
265
|
-
def logger_info_ap msg
|
266
|
-
@logger.info msg
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
class MissingInteractionsGet
|
271
|
-
include RackHelper
|
272
|
-
|
273
|
-
def initialize name, logger, interaction_list
|
274
|
-
@name = name
|
275
|
-
@logger = logger
|
276
|
-
@interaction_list = interaction_list
|
277
|
-
end
|
278
|
-
|
279
|
-
def match? env
|
280
|
-
env['REQUEST_PATH'].start_with?('/number_of_missing_interactions') &&
|
281
|
-
env['REQUEST_METHOD'] == 'GET'
|
282
|
-
end
|
283
|
-
|
284
|
-
def respond env
|
285
|
-
number_of_missing_interactions = @interaction_list.missing_interactions.size
|
286
|
-
@logger.info "Number of missing interactions for mock \"#{@name}\" = #{number_of_missing_interactions}"
|
287
|
-
[200, {}, ["#{number_of_missing_interactions}"]]
|
288
|
-
end
|
289
|
-
|
290
|
-
end
|
291
|
-
|
292
|
-
class VerificationGet
|
293
|
-
|
294
|
-
include RackHelper
|
295
|
-
|
296
|
-
def initialize name, logger, log_description, interaction_list
|
297
|
-
@name = name
|
298
|
-
@logger = logger
|
299
|
-
@log_description = log_description
|
300
|
-
@interaction_list = interaction_list
|
301
|
-
end
|
302
|
-
|
303
|
-
def match? env
|
304
|
-
env['REQUEST_PATH'].start_with?('/verify') &&
|
305
|
-
env['REQUEST_METHOD'] == 'GET'
|
306
|
-
end
|
307
|
-
|
308
|
-
def respond env
|
309
|
-
if @interaction_list.all_matched?
|
310
|
-
@logger.info "Verifying - interactions matched for example \"#{example_description(env)}\""
|
311
|
-
[200, {}, ['Interactions matched']]
|
312
|
-
else
|
313
|
-
@logger.warn "Verifying - actual interactions do not match expected interactions for example \"#{example_description(env)}\". Interaction diffs:"
|
314
|
-
@logger.ap @interaction_list.interaction_diffs, :warn
|
315
|
-
[500, {}, ["Actual interactions do not match expected interactions for mock #{@name}. See #{@log_description} for details."]]
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
def example_description env
|
320
|
-
params_hash(env)['example_description']
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
class MockService
|
325
|
-
|
326
|
-
def initialize options = {}
|
327
|
-
options = {log_file: STDOUT}.merge options
|
328
|
-
log_stream = options[:log_file]
|
329
|
-
@logger = Logger.new log_stream
|
330
|
-
|
331
|
-
log_description = if log_stream.is_a? File
|
332
|
-
File.absolute_path(log_stream).gsub(Dir.pwd + "/", '')
|
333
|
-
else
|
334
|
-
"standard out/err"
|
335
|
-
end
|
336
|
-
|
337
|
-
interaction_list = InteractionList.new
|
338
|
-
|
339
|
-
@name = options.fetch(:name, "MockService")
|
340
|
-
@handlers = [
|
341
|
-
StartupPoll.new(@name, @logger),
|
342
|
-
CapybaraIdentify.new(@name, @logger),
|
343
|
-
MissingInteractionsGet.new(@name, @logger, interaction_list),
|
344
|
-
VerificationGet.new(@name, @logger, log_description, interaction_list),
|
345
|
-
InteractionPost.new(@name, @logger, interaction_list),
|
346
|
-
InteractionDelete.new(@name, @logger, interaction_list),
|
347
|
-
InteractionReplay.new(@name, @logger, interaction_list)
|
348
|
-
]
|
349
|
-
end
|
350
|
-
|
351
|
-
def to_s
|
352
|
-
"#{@name} #{super.to_s}"
|
353
|
-
end
|
354
|
-
|
355
|
-
def call env
|
356
|
-
response = []
|
357
|
-
begin
|
358
|
-
relevant_handler = @handlers.detect { |handler| handler.match? env }
|
359
|
-
response = relevant_handler.respond env
|
360
|
-
rescue Exception => e
|
361
|
-
@logger.ap 'Error ocurred in mock service:'
|
362
|
-
@logger.ap e
|
363
|
-
@logger.ap e.backtrace
|
364
|
-
raise e
|
365
|
-
end
|
366
|
-
response
|
367
|
-
end
|
368
|
-
|
369
|
-
end
|
370
|
-
end
|
371
|
-
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'json'
|
3
|
+
require 'logger'
|
4
|
+
require 'awesome_print'
|
5
|
+
require 'awesome_print/core_ext/logger' #For some reason we get an error indicating that the method 'ap' is private unless we load this specifically
|
6
|
+
require 'pact/consumer/request'
|
7
|
+
require 'pact/consumer/mock_service/interaction_list'
|
8
|
+
require 'pact/consumer/mock_service/startup_poll'
|
9
|
+
require 'pact/consumer/mock_service/interaction_delete'
|
10
|
+
require 'pact/consumer/mock_service/interaction_post'
|
11
|
+
require 'pact/consumer/mock_service/interaction_replay'
|
12
|
+
require 'pact/consumer/mock_service/missing_interactions_get'
|
13
|
+
require 'pact/consumer/mock_service/verification_get'
|
14
|
+
|
15
|
+
AwesomePrint.defaults = {
|
16
|
+
indent: -2,
|
17
|
+
plain: true,
|
18
|
+
index: false
|
19
|
+
}
|
20
|
+
|
21
|
+
module Pact
|
22
|
+
module Consumer
|
23
|
+
|
24
|
+
class MockService
|
25
|
+
|
26
|
+
def initialize options = {}
|
27
|
+
options = {log_file: STDOUT}.merge options
|
28
|
+
log_stream = options[:log_file]
|
29
|
+
@logger = Logger.new log_stream
|
30
|
+
|
31
|
+
log_description = if log_stream.is_a? File
|
32
|
+
File.absolute_path(log_stream).gsub(Dir.pwd + "/", '')
|
33
|
+
else
|
34
|
+
"standard out/err"
|
35
|
+
end
|
36
|
+
|
37
|
+
interaction_list = InteractionList.new
|
38
|
+
|
39
|
+
@name = options.fetch(:name, "MockService")
|
40
|
+
@handlers = [
|
41
|
+
StartupPoll.new(@name, @logger),
|
42
|
+
MissingInteractionsGet.new(@name, @logger, interaction_list),
|
43
|
+
VerificationGet.new(@name, @logger, log_description, interaction_list),
|
44
|
+
InteractionPost.new(@name, @logger, interaction_list),
|
45
|
+
InteractionDelete.new(@name, @logger, interaction_list),
|
46
|
+
InteractionReplay.new(@name, @logger, interaction_list)
|
47
|
+
]
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
"#{@name} #{super.to_s}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def call env
|
55
|
+
response = []
|
56
|
+
begin
|
57
|
+
relevant_handler = @handlers.detect { |handler| handler.match? env }
|
58
|
+
response = relevant_handler.respond env
|
59
|
+
rescue Exception => e
|
60
|
+
@logger.ap 'Error ocurred in mock service:'
|
61
|
+
@logger.ap e
|
62
|
+
@logger.ap e.backtrace
|
63
|
+
raise e
|
64
|
+
end
|
65
|
+
response
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|