substation 0.0.8 → 0.0.9
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/.travis.yml +4 -0
- data/Changelog.md +92 -2
- data/Gemfile.devtools +19 -17
- data/README.md +116 -46
- data/config/flay.yml +2 -2
- data/config/mutant.yml +1 -0
- data/config/reek.yml +11 -5
- data/config/rubocop.yml +35 -0
- data/lib/substation.rb +10 -1
- data/lib/substation/chain.rb +108 -64
- data/lib/substation/chain/dsl.rb +62 -37
- data/lib/substation/dispatcher.rb +3 -1
- data/lib/substation/environment.rb +9 -6
- data/lib/substation/environment/dsl.rb +4 -3
- data/lib/substation/observer.rb +2 -0
- data/lib/substation/processor.rb +106 -7
- data/lib/substation/processor/evaluator.rb +98 -7
- data/lib/substation/processor/transformer.rb +26 -0
- data/lib/substation/processor/wrapper.rb +5 -3
- data/lib/substation/request.rb +12 -1
- data/lib/substation/response.rb +13 -0
- data/lib/substation/utils.rb +3 -1
- data/lib/substation/version.rb +3 -1
- data/spec/integration/substation/dispatcher/call_spec.rb +12 -12
- data/spec/spec_helper.rb +39 -32
- data/spec/unit/substation/chain/call_spec.rb +205 -29
- data/spec/unit/substation/chain/class_methods/failure_response_spec.rb +16 -0
- data/spec/unit/substation/chain/dsl/builder/dsl_spec.rb +7 -4
- data/spec/unit/substation/chain/dsl/class_methods/build_spec.rb +24 -0
- data/spec/unit/substation/chain/dsl/failure_chain_spec.rb +35 -0
- data/spec/unit/substation/chain/dsl/processors_spec.rb +8 -6
- data/spec/unit/substation/chain/dsl/use_spec.rb +1 -1
- data/spec/unit/substation/chain/each_spec.rb +5 -9
- data/spec/unit/substation/chain/failure_data/equalizer_spec.rb +46 -0
- data/spec/unit/substation/chain/failure_data/hash_spec.rb +13 -0
- data/spec/unit/substation/dispatcher/action/call_spec.rb +2 -1
- data/spec/unit/substation/dispatcher/action/class_methods/coerce_spec.rb +7 -5
- data/spec/unit/substation/dispatcher/call_spec.rb +2 -2
- data/spec/unit/substation/dispatcher/class_methods/coerce_spec.rb +6 -6
- data/spec/unit/substation/environment/chain_spec.rb +22 -27
- data/spec/unit/substation/environment/class_methods/build_spec.rb +11 -4
- data/spec/unit/substation/environment/dsl/class_methods/registry_spec.rb +5 -3
- data/spec/unit/substation/environment/dsl/register_spec.rb +8 -3
- data/spec/unit/substation/environment/dsl/registry_spec.rb +5 -3
- data/spec/unit/substation/environment/equalizer_spec.rb +25 -0
- data/spec/unit/substation/observer/chain/call_spec.rb +2 -0
- data/spec/unit/substation/observer/class_methods/coerce_spec.rb +2 -0
- data/spec/unit/substation/observer/null/call_spec.rb +2 -0
- data/spec/unit/substation/processor/evaluator/call_spec.rb +20 -10
- data/spec/unit/substation/processor/evaluator/class_methods/new_spec.rb +9 -0
- data/spec/unit/substation/processor/evaluator/data/call_spec.rb +34 -0
- data/spec/unit/substation/processor/evaluator/pivot/call_spec.rb +34 -0
- data/spec/unit/substation/processor/evaluator/request/call_spec.rb +34 -0
- data/spec/unit/substation/processor/fallible/name_spec.rb +15 -0
- data/spec/unit/substation/processor/fallible/with_failure_chain_spec.rb +18 -0
- data/spec/unit/substation/processor/incoming/result_spec.rb +25 -0
- data/spec/unit/substation/processor/outgoing/call_spec.rb +28 -0
- data/spec/unit/substation/processor/outgoing/name_spec.rb +14 -0
- data/spec/unit/substation/processor/outgoing/success_predicate_spec.rb +15 -0
- data/spec/unit/substation/{chain/outgoing → processor}/result_spec.rb +4 -3
- data/spec/unit/substation/processor/success_predicate_spec.rb +22 -0
- data/spec/unit/substation/processor/transformer/call_spec.rb +21 -0
- data/spec/unit/substation/processor/wrapper/call_spec.rb +9 -7
- data/spec/unit/substation/request/env_spec.rb +3 -2
- data/spec/unit/substation/request/error_spec.rb +2 -1
- data/spec/unit/substation/request/input_spec.rb +3 -2
- data/spec/unit/substation/request/name_spec.rb +15 -0
- data/spec/unit/substation/request/success_spec.rb +2 -1
- data/spec/unit/substation/response/env_spec.rb +3 -2
- data/spec/unit/substation/response/failure/success_predicate_spec.rb +2 -1
- data/spec/unit/substation/response/input_spec.rb +3 -2
- data/spec/unit/substation/response/output_spec.rb +2 -1
- data/spec/unit/substation/response/request_spec.rb +3 -2
- data/spec/unit/substation/response/success/success_predicate_spec.rb +2 -1
- data/spec/unit/substation/response/to_request_spec.rb +19 -0
- data/spec/unit/substation/utils/class_methods/coerce_callable_spec.rb +14 -12
- data/spec/unit/substation/utils/class_methods/const_get_spec.rb +6 -6
- data/spec/unit/substation/utils/class_methods/symbolize_keys_spec.rb +4 -4
- metadata +25 -9
- data/lib/substation/processor/pivot.rb +0 -25
- data/spec/unit/substation/chain/class_methods/build_spec.rb +0 -31
- data/spec/unit/substation/chain/dsl/class_methods/processors_spec.rb +0 -23
- data/spec/unit/substation/chain/incoming/result_spec.rb +0 -21
- data/spec/unit/substation/chain/outgoing/call_spec.rb +0 -25
- data/spec/unit/substation/processor/pivot/call_spec.rb +0 -16
data/lib/substation/utils.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
module Substation
|
|
2
4
|
|
|
3
5
|
# A collection of utility methods
|
|
@@ -12,7 +14,7 @@ module Substation
|
|
|
12
14
|
#
|
|
13
15
|
# @api private
|
|
14
16
|
def self.const_get(name)
|
|
15
|
-
list = name.to_s.split(
|
|
17
|
+
list = name.to_s.split('::')
|
|
16
18
|
list.shift if list.first.empty?
|
|
17
19
|
obj = Object
|
|
18
20
|
list.each do |const|
|
data/lib/substation/version.rb
CHANGED
|
@@ -181,8 +181,8 @@ module App
|
|
|
181
181
|
end # module Actions
|
|
182
182
|
|
|
183
183
|
module Observers
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
LOG_EVENT = ->(response) { response }
|
|
185
|
+
SEND_EMAIL = ->(response) { response }
|
|
186
186
|
end
|
|
187
187
|
|
|
188
188
|
DB = Database.new({
|
|
@@ -198,8 +198,8 @@ module App
|
|
|
198
198
|
:create_person => {
|
|
199
199
|
:action => Actions::CreatePerson,
|
|
200
200
|
:observer => [
|
|
201
|
-
Observers::
|
|
202
|
-
Observers::
|
|
201
|
+
Observers::LOG_EVENT,
|
|
202
|
+
Observers::SEND_EMAIL
|
|
203
203
|
]
|
|
204
204
|
}
|
|
205
205
|
}
|
|
@@ -213,11 +213,11 @@ end
|
|
|
213
213
|
|
|
214
214
|
describe App::APP, '#call' do
|
|
215
215
|
|
|
216
|
-
context
|
|
216
|
+
context 'when dispatching an action' do
|
|
217
217
|
subject { object.call(action, input) }
|
|
218
218
|
|
|
219
219
|
let(:object) { described_class }
|
|
220
|
-
let(:request) { Substation::Request.new(env, input) }
|
|
220
|
+
let(:request) { Substation::Request.new(action, env, input) }
|
|
221
221
|
let(:env) { App::Environment.new(storage) }
|
|
222
222
|
let(:storage) { App::Storage.new(App::DB) }
|
|
223
223
|
let(:response) { Substation::Response::Success.new(request, output) }
|
|
@@ -225,7 +225,7 @@ describe App::APP, '#call' do
|
|
|
225
225
|
let(:john) { App::Models::Person.new(:id => 1, :name => 'John') }
|
|
226
226
|
let(:jane) { App::Models::Person.new(:id => 2, :name => 'Jane') }
|
|
227
227
|
|
|
228
|
-
context
|
|
228
|
+
context 'with no input data' do
|
|
229
229
|
let(:action) { :list_people }
|
|
230
230
|
let(:input) { nil }
|
|
231
231
|
let(:output) { [ john ] }
|
|
@@ -233,8 +233,8 @@ describe App::APP, '#call' do
|
|
|
233
233
|
it { should eql(response) }
|
|
234
234
|
end
|
|
235
235
|
|
|
236
|
-
context
|
|
237
|
-
context
|
|
236
|
+
context 'with input data' do
|
|
237
|
+
context 'and no observer' do
|
|
238
238
|
let(:action) { :load_person }
|
|
239
239
|
let(:input) { 1 }
|
|
240
240
|
let(:output) { john }
|
|
@@ -242,14 +242,14 @@ describe App::APP, '#call' do
|
|
|
242
242
|
it { should eq(response) }
|
|
243
243
|
end
|
|
244
244
|
|
|
245
|
-
context
|
|
245
|
+
context 'and observers' do
|
|
246
246
|
let(:action) { :create_person }
|
|
247
247
|
let(:input) { jane }
|
|
248
248
|
let(:output) { [ john, jane ] }
|
|
249
249
|
|
|
250
250
|
before do
|
|
251
|
-
App::Observers::
|
|
252
|
-
App::Observers::
|
|
251
|
+
App::Observers::LOG_EVENT.should_receive(:call).with(response).ordered
|
|
252
|
+
App::Observers::SEND_EMAIL.should_receive(:call).with(response).ordered
|
|
253
253
|
end
|
|
254
254
|
|
|
255
255
|
it { should eql(response) }
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
require 'devtools/spec_helper'
|
|
2
4
|
|
|
3
5
|
require 'concord' # makes spec setup easier
|
|
4
6
|
|
|
7
|
+
if ENV['COVERAGE'] == 'true'
|
|
8
|
+
require 'simplecov'
|
|
9
|
+
require 'coveralls'
|
|
10
|
+
|
|
11
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
|
12
|
+
SimpleCov::Formatter::HTMLFormatter,
|
|
13
|
+
Coveralls::SimpleCov::Formatter
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
SimpleCov.start do
|
|
17
|
+
command_name 'spec:unit'
|
|
18
|
+
add_filter 'config'
|
|
19
|
+
add_filter 'spec'
|
|
20
|
+
minimum_coverage 100
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
require 'substation'
|
|
25
|
+
|
|
5
26
|
module Spec
|
|
6
27
|
|
|
7
28
|
def self.response_data
|
|
@@ -28,7 +49,18 @@ module Spec
|
|
|
28
49
|
end
|
|
29
50
|
|
|
30
51
|
class Processor
|
|
31
|
-
include
|
|
52
|
+
include Substation::Processor::Fallible
|
|
53
|
+
attr_reader :name
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class Presenter
|
|
57
|
+
include Concord.new(:data)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class Transformer
|
|
61
|
+
def self.call(response)
|
|
62
|
+
:transformed
|
|
63
|
+
end
|
|
32
64
|
end
|
|
33
65
|
|
|
34
66
|
module Handler
|
|
@@ -51,6 +83,10 @@ module Spec
|
|
|
51
83
|
end
|
|
52
84
|
end
|
|
53
85
|
|
|
86
|
+
def self.call(data)
|
|
87
|
+
new.call(data)
|
|
88
|
+
end
|
|
89
|
+
|
|
54
90
|
def call(data)
|
|
55
91
|
if data == :success
|
|
56
92
|
Result::Success.new(data)
|
|
@@ -66,43 +102,14 @@ module Spec
|
|
|
66
102
|
end
|
|
67
103
|
end
|
|
68
104
|
|
|
69
|
-
class Wrapper
|
|
70
|
-
class Presenter
|
|
71
|
-
include Concord.new(:data)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
include Concord.new(:data)
|
|
75
|
-
|
|
76
|
-
def call(data)
|
|
77
|
-
Presenter.new(data)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
105
|
end
|
|
81
106
|
|
|
82
107
|
FAKE_HANDLER = Object.new
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
if ENV['COVERAGE'] == 'true'
|
|
88
|
-
require 'simplecov'
|
|
89
|
-
require 'coveralls'
|
|
108
|
+
FAKE_ENV = Object.new
|
|
109
|
+
FAKE_PROCESSOR = Processor.new(:test, FAKE_HANDLER, [])
|
|
90
110
|
|
|
91
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
|
92
|
-
SimpleCov::Formatter::HTMLFormatter,
|
|
93
|
-
Coveralls::SimpleCov::Formatter
|
|
94
|
-
]
|
|
95
|
-
|
|
96
|
-
SimpleCov.start do
|
|
97
|
-
command_name 'spec:unit'
|
|
98
|
-
add_filter 'config'
|
|
99
|
-
add_filter 'spec'
|
|
100
|
-
minimum_coverage 100
|
|
101
|
-
end
|
|
102
111
|
end
|
|
103
112
|
|
|
104
|
-
require 'substation'
|
|
105
|
-
|
|
106
113
|
include Substation
|
|
107
114
|
|
|
108
115
|
RSpec.configure do |config|
|
|
@@ -6,52 +6,228 @@ describe Chain, '#call' do
|
|
|
6
6
|
|
|
7
7
|
subject { object.call(request) }
|
|
8
8
|
|
|
9
|
-
let(:object)
|
|
10
|
-
let(:
|
|
11
|
-
let(:
|
|
12
|
-
let(:
|
|
13
|
-
let(:
|
|
14
|
-
|
|
15
|
-
let(:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
9
|
+
let(:object) { described_class.new(processors, exception_chain) }
|
|
10
|
+
let(:exception_chain) { mock(:call => response) }
|
|
11
|
+
let(:processors) { [ processor_1, processor_2, processor_3 ] }
|
|
12
|
+
let(:request) { Request.new(name, env, input) }
|
|
13
|
+
let(:name) { mock }
|
|
14
|
+
let(:env) { mock }
|
|
15
|
+
let(:input) { mock }
|
|
16
|
+
|
|
17
|
+
let(:failure_chain) { mock }
|
|
18
|
+
let(:handler) { mock }
|
|
19
|
+
|
|
20
|
+
let(:processor_1_name) { mock }
|
|
21
|
+
let(:processor_2_name) { mock }
|
|
22
|
+
let(:processor_3_name) { mock }
|
|
23
23
|
|
|
24
|
-
context
|
|
25
|
-
let(:
|
|
24
|
+
context 'when all processors are successful' do
|
|
25
|
+
let(:processor_1) {
|
|
26
26
|
Class.new {
|
|
27
|
-
include Substation::
|
|
27
|
+
include Substation::Processor::Incoming
|
|
28
28
|
def call(request)
|
|
29
|
-
request.success(
|
|
29
|
+
request.success(:success_1)
|
|
30
|
+
end
|
|
31
|
+
}.new(processor_1_name, handler, failure_chain)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let(:processor_2) {
|
|
35
|
+
Class.new {
|
|
36
|
+
include Substation::Processor::Pivot
|
|
37
|
+
def call(request)
|
|
38
|
+
request.success(:success_2)
|
|
39
|
+
end
|
|
40
|
+
}.new(processor_2_name, handler, failure_chain)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let(:processor_3) {
|
|
44
|
+
Class.new {
|
|
45
|
+
include Substation::Processor::Outgoing
|
|
46
|
+
def call(response)
|
|
47
|
+
respond_with(response, :success_3)
|
|
30
48
|
end
|
|
31
|
-
}.new
|
|
49
|
+
}.new(processor_3_name, handler)
|
|
32
50
|
}
|
|
33
51
|
|
|
34
|
-
let(:response)
|
|
52
|
+
let(:response) { Response::Success.new(current_request, :success_3) }
|
|
53
|
+
let(:current_request) { Request.new(name, env, :success_1) }
|
|
35
54
|
|
|
36
55
|
it { should eql(response) }
|
|
37
56
|
end
|
|
38
57
|
|
|
39
|
-
context
|
|
40
|
-
|
|
58
|
+
context 'when an incoming processor is not successful' do
|
|
59
|
+
|
|
60
|
+
let(:processor_2) {
|
|
41
61
|
Class.new {
|
|
42
|
-
include Substation::
|
|
62
|
+
include Substation::Processor::Pivot
|
|
43
63
|
def call(request)
|
|
44
|
-
request.
|
|
64
|
+
request.success(:success_1)
|
|
45
65
|
end
|
|
46
|
-
}.new
|
|
66
|
+
}.new(processor_2_name, handler, failure_chain)
|
|
47
67
|
}
|
|
48
68
|
|
|
49
|
-
let(:
|
|
69
|
+
let(:processor_3) {
|
|
70
|
+
Class.new {
|
|
71
|
+
include Substation::Processor::Outgoing
|
|
72
|
+
def call(response)
|
|
73
|
+
respond_with(response, :success_3)
|
|
74
|
+
end
|
|
75
|
+
}.new(processor_3_name, handler)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let(:response_class) { Response::Failure }
|
|
79
|
+
|
|
80
|
+
context 'because it returned a failure response' do
|
|
81
|
+
let(:processor_1) {
|
|
82
|
+
Class.new {
|
|
83
|
+
include Substation::Processor::Incoming
|
|
84
|
+
def call(request)
|
|
85
|
+
request.error(:error_1)
|
|
86
|
+
end
|
|
87
|
+
}.new(processor_1_name, handler, failure_chain)
|
|
88
|
+
}
|
|
50
89
|
|
|
51
|
-
|
|
52
|
-
|
|
90
|
+
let(:response) { Response::Failure.new(request, :error_1) }
|
|
91
|
+
|
|
92
|
+
it { should eql(response) }
|
|
53
93
|
end
|
|
54
94
|
|
|
55
|
-
it
|
|
95
|
+
context 'because it raised an uncaught exception' do
|
|
96
|
+
let(:processor_1) {
|
|
97
|
+
Class.new {
|
|
98
|
+
include Substation::Processor::Incoming
|
|
99
|
+
def call(request)
|
|
100
|
+
raise RuntimeError, 'exception_1'
|
|
101
|
+
end
|
|
102
|
+
}.new(processor_1_name, handler, failure_chain)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let(:response) { Response::Failure.new(request, data) }
|
|
106
|
+
let(:data) { Chain::FailureData.new(request, RuntimeError.new('exception_1')) }
|
|
107
|
+
|
|
108
|
+
it { should eql(response) }
|
|
109
|
+
|
|
110
|
+
it 'wraps the original exception instance' do
|
|
111
|
+
expect(subject.output.exception.message).to eql('exception_1')
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'calls the failure chain' do
|
|
115
|
+
exception_chain.should_receive(:call).with(response)
|
|
116
|
+
subject
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
context 'when the pivot processor is not successful' do
|
|
122
|
+
let(:processor_1) {
|
|
123
|
+
Class.new {
|
|
124
|
+
include Substation::Processor::Incoming
|
|
125
|
+
def call(request)
|
|
126
|
+
request.success(:success_1)
|
|
127
|
+
end
|
|
128
|
+
}.new(processor_1_name, handler, failure_chain)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let(:processor_3) {
|
|
132
|
+
Class.new {
|
|
133
|
+
include Substation::Processor::Outgoing
|
|
134
|
+
def call(response)
|
|
135
|
+
response
|
|
136
|
+
end
|
|
137
|
+
}.new(processor_3_name, handler)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let(:response_class) { Response::Failure }
|
|
141
|
+
|
|
142
|
+
context 'because it returned a failure response' do
|
|
143
|
+
let(:processor_2) {
|
|
144
|
+
Class.new {
|
|
145
|
+
include Substation::Processor::Pivot
|
|
146
|
+
def call(request)
|
|
147
|
+
request.error(:error_2)
|
|
148
|
+
end
|
|
149
|
+
}.new(processor_2_name, handler, failure_chain)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let(:response) { Response::Failure.new(current_request, :error_2) }
|
|
153
|
+
let(:current_request) { Request.new(name, env, :success_1) }
|
|
154
|
+
|
|
155
|
+
it { should eql(response) }
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
context 'because it raised an uncaught exception' do
|
|
159
|
+
let(:processor_2) {
|
|
160
|
+
Class.new {
|
|
161
|
+
include Substation::Processor::Pivot
|
|
162
|
+
def call(request)
|
|
163
|
+
raise RuntimeError, 'exception_2'
|
|
164
|
+
end
|
|
165
|
+
}.new(processor_2_name, handler, failure_chain)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let(:response) { Response::Failure.new(request, data) }
|
|
169
|
+
let(:data) { Chain::FailureData.new(current_request, RuntimeError.new('exception_2')) }
|
|
170
|
+
let(:current_request) { Request.new(name, env, :success_1) }
|
|
171
|
+
|
|
172
|
+
it { should eql(response) }
|
|
173
|
+
|
|
174
|
+
it 'wraps the original exception instance' do
|
|
175
|
+
expect(subject.output.exception.message).to eql('exception_2')
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it 'calls the failure chain' do
|
|
179
|
+
exception_chain.should_receive(:call).with(response)
|
|
180
|
+
subject
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
context 'when an outgoing processor is not successful' do
|
|
186
|
+
let(:processor_1) {
|
|
187
|
+
Class.new {
|
|
188
|
+
include Substation::Processor::Incoming
|
|
189
|
+
def call(request)
|
|
190
|
+
request.success(:success_1)
|
|
191
|
+
end
|
|
192
|
+
}.new(processor_1_name, handler, failure_chain)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let(:processor_2) {
|
|
196
|
+
Class.new {
|
|
197
|
+
include Substation::Processor::Pivot
|
|
198
|
+
def call(response)
|
|
199
|
+
response.success(:success_2)
|
|
200
|
+
end
|
|
201
|
+
}.new(processor_2_name, handler, failure_chain)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
let(:response_class) { Response::Failure }
|
|
205
|
+
|
|
206
|
+
context 'because it raised an uncaught exception' do
|
|
207
|
+
let(:processor_3) {
|
|
208
|
+
Class.new {
|
|
209
|
+
include Substation::Processor::Outgoing
|
|
210
|
+
def call(response)
|
|
211
|
+
raise RuntimeError, 'exception_3'
|
|
212
|
+
end
|
|
213
|
+
}.new(processor_3_name, handler)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let(:response) { Response::Failure.new(request, data) }
|
|
217
|
+
let(:data) { Chain::FailureData.new(current_response, RuntimeError.new('exception_3')) }
|
|
218
|
+
let(:current_request) { Request.new(name, env, :success_1) }
|
|
219
|
+
let(:current_response) { Response::Success.new(current_request, :success_2) }
|
|
220
|
+
|
|
221
|
+
it { should eql(response) }
|
|
222
|
+
|
|
223
|
+
it 'wraps the original exception instance' do
|
|
224
|
+
expect(subject.output.exception.message).to eql('exception_3')
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it 'calls the failure chain' do
|
|
228
|
+
exception_chain.should_receive(:call).with(response)
|
|
229
|
+
subject
|
|
230
|
+
end
|
|
231
|
+
end
|
|
56
232
|
end
|
|
57
233
|
end
|