ruby_cqrs 0.2.0
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.
- checksums.yaml +7 -0
- data/License.txt +21 -0
- data/README.md +33 -0
- data/lib/ruby_cqrs/data/event_store.rb +13 -0
- data/lib/ruby_cqrs/data/in_memory_event_store.rb +70 -0
- data/lib/ruby_cqrs/data/serialization.rb +30 -0
- data/lib/ruby_cqrs/domain/aggregate.rb +107 -0
- data/lib/ruby_cqrs/domain/aggregate_repository.rb +122 -0
- data/lib/ruby_cqrs/domain/event.rb +10 -0
- data/lib/ruby_cqrs/domain/snapshot.rb +9 -0
- data/lib/ruby_cqrs/domain/snapshotable.rb +48 -0
- data/lib/ruby_cqrs/error.rb +3 -0
- data/lib/ruby_cqrs/guid.rb +13 -0
- data/lib/ruby_cqrs/version.rb +3 -0
- data/lib/ruby_cqrs.rb +12 -0
- data/spec/feature/basic_usage_spec.rb +177 -0
- data/spec/feature/snapshot_spec.rb +216 -0
- data/spec/fixture/typical_domain.rb +182 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/matchers.rb +8 -0
- data/spec/unit/aggregate_repository_spec.rb +332 -0
- data/spec/unit/aggregate_spec.rb +123 -0
- data/spec/unit/in_memory_event_store_spec.rb +404 -0
- data/spec/unit/serialization_spec.rb +52 -0
- metadata +120 -0
@@ -0,0 +1,332 @@
|
|
1
|
+
require_relative('../spec_helper')
|
2
|
+
|
3
|
+
describe RubyCqrs::Domain::AggregateRepository do
|
4
|
+
let(:unsorted_event_records) { [
|
5
|
+
{ :aggregate_id => SomeDomain::AGGREGATE_ID,
|
6
|
+
:event_type => SomeDomain::SecondEvent.name,
|
7
|
+
:version => 2,
|
8
|
+
:data => '' },
|
9
|
+
{ :aggregate_id => SomeDomain::AGGREGATE_ID,
|
10
|
+
:event_type => SomeDomain::FirstEvent.name,
|
11
|
+
:version => 1,
|
12
|
+
:data => '' } ] }
|
13
|
+
let(:aggregate_id) { SomeDomain::AGGREGATE_ID }
|
14
|
+
let(:event_store_load_result) { { :aggregate_id => aggregate_id,
|
15
|
+
:aggregate_type => 'SomeDomain::AggregateRoot',
|
16
|
+
:events => unsorted_event_records } }
|
17
|
+
let(:event_store) do
|
18
|
+
_event_store = (Class.new { include RubyCqrs::Data::EventStore}).new
|
19
|
+
allow(_event_store).to receive(:load_by).and_return(event_store_load_result)
|
20
|
+
_event_store
|
21
|
+
end
|
22
|
+
let(:command_context) { Object.new }
|
23
|
+
let(:repository) { RubyCqrs::Domain::AggregateRepository.new event_store, command_context }
|
24
|
+
let(:aggregate_type) { SomeDomain::AggregateRoot }
|
25
|
+
|
26
|
+
describe '#new' do
|
27
|
+
context 'when expecting arguments' do
|
28
|
+
it 'raises ArgumentError when the first argument is not an descendant from EventStore' do
|
29
|
+
expect { RubyCqrs::Domain::AggregateRepository.new Object.new, command_context }.to raise_error ArgumentError
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'is initialized with an EventStore instance and an CommandContext instance' do
|
33
|
+
RubyCqrs::Domain::AggregateRepository.new event_store, command_context
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#find_by' do
|
39
|
+
context 'when expecting arguments' do
|
40
|
+
it 'raises ArgumentError when aggregate_id is nil' do
|
41
|
+
expect { repository.find_by nil }.to raise_error ArgumentError
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'raises ArgumentError when aggregate_id is not a valid guid' do
|
45
|
+
expect { repository.find_by 'some_invalid_guid' }.to raise_error ArgumentError
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "delegates the actual data loading to the EventStore instance's #load_by" do
|
50
|
+
expect(event_store).to receive(:load_by) do |some_guid, some_command_context|
|
51
|
+
expect(some_guid).to be_a_valid_uuid
|
52
|
+
expect(some_command_context).to be(command_context)
|
53
|
+
end.and_return event_store_load_result
|
54
|
+
|
55
|
+
repository.find_by(aggregate_id)
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when the specified aggregate could not be found' do
|
59
|
+
let(:empty_event_store) do
|
60
|
+
_event_store = (Class.new { include RubyCqrs::Data::EventStore}).new
|
61
|
+
allow(_event_store).to receive(:load_by).and_return(nil)
|
62
|
+
_event_store
|
63
|
+
end
|
64
|
+
let(:matches_nothing_repository) { RubyCqrs::Domain::AggregateRepository.new\
|
65
|
+
empty_event_store, command_context }
|
66
|
+
|
67
|
+
it 'raises error of type AggregateNotFound' do
|
68
|
+
expect { matches_nothing_repository.find_by(aggregate_id) }.to \
|
69
|
+
raise_error(RubyCqrs::AggregateNotFound)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when the specified aggregate is found' do
|
74
|
+
let(:aggregate) { repository.find_by(aggregate_id) }
|
75
|
+
let(:expeced_version) { unsorted_event_records.size }
|
76
|
+
let(:expeced_source_version) { unsorted_event_records.size }
|
77
|
+
|
78
|
+
it 'returns an instance of expected type' do
|
79
|
+
expect(aggregate).to be_an_instance_of(aggregate_type)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'returns an instance of expected aggregate_id' do
|
83
|
+
expect(aggregate.aggregate_id).to eq(aggregate_id)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'returns an instance of expected version' do
|
87
|
+
expect(aggregate.version).to eq(expeced_version)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'returns an instance of expected source_version' do
|
91
|
+
expect(aggregate.instance_variable_get(:@source_version)).to eq(expeced_source_version)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#save' do
|
97
|
+
context 'when expecting arguments' do
|
98
|
+
it 'raises ArgumentError when given 0 or nil argument or an 0 length enumerable' do
|
99
|
+
expect { repository.save }.to raise_error ArgumentError
|
100
|
+
expect { repository.save nil }.to raise_error ArgumentError
|
101
|
+
expect { repository.save [] }.to raise_error ArgumentError
|
102
|
+
end
|
103
|
+
it 'raises ArgumentError when the first argument is not an descendant from AggregateBase' do
|
104
|
+
expect { repository.save Object.new }.to raise_error ArgumentError
|
105
|
+
end
|
106
|
+
it 'raises ArgumentError when the first argument is not an enumerable of AggregateBase' do
|
107
|
+
expect { repository.save [ Object.new ] }.to raise_error ArgumentError
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'during the saving process' do
|
112
|
+
context 'when saving a single aggregate' do
|
113
|
+
context 'when the aggregate has not been changed' do
|
114
|
+
let(:unchanged_aggregate) do
|
115
|
+
aggregate_type.new
|
116
|
+
end
|
117
|
+
|
118
|
+
it "short-circuit without calling the EventStore instance's #save" do
|
119
|
+
expect(event_store).to_not receive(:save)
|
120
|
+
repository.save unchanged_aggregate
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'when the aggregate has been changed' do
|
125
|
+
let(:changed_aggregate) do
|
126
|
+
_aggregate = aggregate_type.new
|
127
|
+
_aggregate.test_fire
|
128
|
+
_aggregate.test_fire_ag
|
129
|
+
_aggregate
|
130
|
+
end
|
131
|
+
|
132
|
+
it "delegates event persistence to the EventStore instance's #save" do
|
133
|
+
expect(event_store).to receive(:save) do |aggregate_changes, some_command_context|
|
134
|
+
expect(aggregate_changes.size).to eq(1)
|
135
|
+
expect(aggregate_changes[0][:aggregate_id]).to eq(changed_aggregate.aggregate_id)
|
136
|
+
expect(aggregate_changes[0][:aggregate_type]).to eq(changed_aggregate.class.name)
|
137
|
+
expect(aggregate_changes[0][:events].size).to eq(2)
|
138
|
+
expect(aggregate_changes[0][:events][0][:aggregate_id]).to eq(changed_aggregate.aggregate_id)
|
139
|
+
expect(aggregate_changes[0][:events][0][:version]).to eq(1)
|
140
|
+
expect(aggregate_changes[0][:events][0][:event_type]).to eq(SomeDomain::ThirdEvent.name)
|
141
|
+
expect(aggregate_changes[0][:events][0][:data]).to_not be_nil
|
142
|
+
expect(aggregate_changes[0][:events][1][:aggregate_id]).to eq(changed_aggregate.aggregate_id)
|
143
|
+
expect(aggregate_changes[0][:events][1][:version]).to eq(2)
|
144
|
+
expect(aggregate_changes[0][:events][1][:event_type]).to eq(SomeDomain::ForthEvent.name)
|
145
|
+
expect(aggregate_changes[0][:events][1][:data]).to_not be_nil
|
146
|
+
expect(some_command_context).to be(command_context)
|
147
|
+
end
|
148
|
+
|
149
|
+
repository.save(changed_aggregate)
|
150
|
+
end
|
151
|
+
|
152
|
+
describe 'after the saving process finished successfully' do
|
153
|
+
it 'has both version and source_version set to the same value' do
|
154
|
+
expect(event_store).to receive(:save)
|
155
|
+
|
156
|
+
repository.save(changed_aggregate)
|
157
|
+
|
158
|
+
expect(changed_aggregate.version).to eq(2)
|
159
|
+
expect(changed_aggregate.instance_variable_get(:@source_version)).to eq(2)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe 'if some error happened during the saving process' do
|
164
|
+
before(:each) do
|
165
|
+
expect(event_store).to receive(:save) { raise RubyCqrs::AggregateConcurrencyError }
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'bubbles up that error directly' do
|
169
|
+
expect { repository.save(changed_aggregate) }.to\
|
170
|
+
raise_error(RubyCqrs::AggregateConcurrencyError)
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'has source_version unchanged' do
|
174
|
+
original_source_version = changed_aggregate.instance_variable_get(:@source_version)
|
175
|
+
|
176
|
+
expect { repository.save(changed_aggregate) }.to\
|
177
|
+
raise_error(RubyCqrs::AggregateConcurrencyError)
|
178
|
+
|
179
|
+
expect(changed_aggregate.instance_variable_get(:@source_version)).to eq(original_source_version)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'when saving 2 instances of the same aggregate' do
|
186
|
+
it 'raises AggregateInstanceDuplicatedError and nothing should be changed' do
|
187
|
+
aggregate_1 = aggregate_type.new
|
188
|
+
aggregate_2 = aggregate_1.dup
|
189
|
+
aggregate_1.test_fire
|
190
|
+
aggregate_2.test_fire
|
191
|
+
aggregates = [ aggregate_1, aggregate_2 ]
|
192
|
+
expect{ repository.save aggregates }.to raise_error(RubyCqrs::AggregateInstanceDuplicatedError)
|
193
|
+
expect(aggregate_1.version).to_not eq(aggregate_1.instance_variable_get(:@source_verrsion))
|
194
|
+
expect(aggregate_2.version).to_not eq(aggregate_2.instance_variable_get(:@source_verrsion))
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context 'when saving 2 aggregates' do
|
199
|
+
context 'when none of the aggregates have been changed' do
|
200
|
+
let(:unchanged_aggregates) do
|
201
|
+
[ aggregate_type.new, aggregate_type.new ]
|
202
|
+
end
|
203
|
+
|
204
|
+
it "short-circuit without calling the EventStore instance's #save" do
|
205
|
+
expect(event_store).to_not receive(:save)
|
206
|
+
repository.save unchanged_aggregates
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'when one of the aggregates has been changed' do
|
211
|
+
let(:two_aggregates) do
|
212
|
+
_aggregate = aggregate_type.new
|
213
|
+
_aggregate.test_fire
|
214
|
+
_aggregate.test_fire_ag
|
215
|
+
[ _aggregate, aggregate_type.new ]
|
216
|
+
end
|
217
|
+
|
218
|
+
it "delegates event persistence to the EventStore instance's #save" do
|
219
|
+
expect(event_store).to receive(:save) do |aggregate_changes, some_command_context|
|
220
|
+
expect(aggregate_changes.size).to eq(1)
|
221
|
+
expect(some_command_context).to be(command_context)
|
222
|
+
end
|
223
|
+
|
224
|
+
repository.save(two_aggregates)
|
225
|
+
end
|
226
|
+
|
227
|
+
describe 'the aggregate that changed, after the saving process finished successfully' do
|
228
|
+
it 'has both version and source_version set to the same value' do
|
229
|
+
expect(event_store).to receive(:save)
|
230
|
+
|
231
|
+
repository.save(two_aggregates)
|
232
|
+
|
233
|
+
expect(two_aggregates[0].version).to eq(2)
|
234
|
+
expect(two_aggregates[0].instance_variable_get(:@source_version)).to eq(2)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe 'the aggregate that did not change, after the saving process finished successfully' do
|
239
|
+
it 'has both version and source_version unchanged' do
|
240
|
+
expect(event_store).to receive(:save)
|
241
|
+
original_version = two_aggregates[1].version
|
242
|
+
original_source_version = two_aggregates[1].instance_variable_get(:@source_version)
|
243
|
+
|
244
|
+
repository.save(two_aggregates)
|
245
|
+
|
246
|
+
expect(two_aggregates[1].version).to eq(original_version)
|
247
|
+
expect(two_aggregates[1].instance_variable_get(:@source_version)).to eq(original_source_version)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
describe 'if some error happened during the saving process' do
|
252
|
+
before(:each) do
|
253
|
+
expect(event_store).to receive(:save) { raise RubyCqrs::AggregateConcurrencyError }
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'bubbles up that error directly' do
|
257
|
+
expect { repository.save(two_aggregates) }.to\
|
258
|
+
raise_error(RubyCqrs::AggregateConcurrencyError)
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'has source_version unchanged' do
|
262
|
+
original_source_version_0 = two_aggregates[0].instance_variable_get(:@source_version)
|
263
|
+
original_source_version_1 = two_aggregates[1].instance_variable_get(:@source_version)
|
264
|
+
|
265
|
+
expect { repository.save(two_aggregates) }.to\
|
266
|
+
raise_error(RubyCqrs::AggregateConcurrencyError)
|
267
|
+
|
268
|
+
expect(two_aggregates[0].instance_variable_get(:@source_version)).to eq(original_source_version_0)
|
269
|
+
expect(two_aggregates[1].instance_variable_get(:@source_version)).to eq(original_source_version_1)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context 'when both aggregates have been changed' do
|
275
|
+
let(:two_aggregates) do
|
276
|
+
_aggregate_1 = aggregate_type.new
|
277
|
+
_aggregate_2 = aggregate_type.new
|
278
|
+
_aggregate_1.test_fire
|
279
|
+
_aggregate_1.test_fire_ag
|
280
|
+
_aggregate_2.test_fire
|
281
|
+
_aggregate_2.test_fire_ag
|
282
|
+
[ _aggregate_2, _aggregate_1 ]
|
283
|
+
end
|
284
|
+
|
285
|
+
it "delegates event persistence to the EventStore instance's #save" do
|
286
|
+
expect(event_store).to receive(:save) do |aggregate_changes, some_command_context|
|
287
|
+
expect(aggregate_changes.size).to eq(2)
|
288
|
+
expect(some_command_context).to be(command_context)
|
289
|
+
end
|
290
|
+
|
291
|
+
repository.save(two_aggregates)
|
292
|
+
end
|
293
|
+
|
294
|
+
describe 'after the saving process finished successfully' do
|
295
|
+
it "has both aggregates' version and source_version set to the same value" do
|
296
|
+
expect(event_store).to receive(:save)
|
297
|
+
|
298
|
+
repository.save(two_aggregates)
|
299
|
+
|
300
|
+
expect(two_aggregates[0].version).to eq(2)
|
301
|
+
expect(two_aggregates[0].instance_variable_get(:@source_version)).to eq(2)
|
302
|
+
expect(two_aggregates[1].version).to eq(2)
|
303
|
+
expect(two_aggregates[1].instance_variable_get(:@source_version)).to eq(2)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe 'if something wrong happened during the saving process' do
|
308
|
+
before(:each) do
|
309
|
+
expect(event_store).to receive(:save) { raise RubyCqrs::AggregateConcurrencyError }
|
310
|
+
end
|
311
|
+
|
312
|
+
it 'bubbles up that error directly' do
|
313
|
+
expect { repository.save(two_aggregates) }.to\
|
314
|
+
raise_error(RubyCqrs::AggregateConcurrencyError)
|
315
|
+
end
|
316
|
+
|
317
|
+
it 'has source_version unchanged' do
|
318
|
+
original_source_version_0 = two_aggregates[0].instance_variable_get(:@source_version)
|
319
|
+
original_source_version_1 = two_aggregates[1].instance_variable_get(:@source_version)
|
320
|
+
|
321
|
+
expect { repository.save(two_aggregates) }.to\
|
322
|
+
raise_error(RubyCqrs::AggregateConcurrencyError)
|
323
|
+
|
324
|
+
expect(two_aggregates[0].instance_variable_get(:@source_version)).to eq(original_source_version_0)
|
325
|
+
expect(two_aggregates[1].instance_variable_get(:@source_version)).to eq(original_source_version_1)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require_relative('../spec_helper')
|
2
|
+
|
3
|
+
describe RubyCqrs::Domain::Aggregate do
|
4
|
+
let(:aggregate_id) { SomeDomain::AGGREGATE_ID }
|
5
|
+
let(:aggregate) { SomeDomain::AggregateRoot.new }
|
6
|
+
let(:unsorted_events) { [ SomeDomain::SecondEvent.new, SomeDomain::FirstEvent.new ] }
|
7
|
+
|
8
|
+
describe '#new' do
|
9
|
+
it 'has aggregate_id initilized as a valid uuid' do
|
10
|
+
expect(aggregate.aggregate_id).to be_a_valid_uuid
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has version initilized as 0' do
|
14
|
+
expect(aggregate.version).to be_zero
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'has source_version initilized as 0' do
|
18
|
+
expect(aggregate.instance_variable_get(:@source_version)).to be_zero
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#raise_event' do
|
23
|
+
it 'raise NotADomainEventError when raising an object that is not a proper event' do
|
24
|
+
expect { aggregate.fire_weird_stuff }.to raise_error(RubyCqrs::NotADomainEventError)
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'after raising an event' do
|
28
|
+
it 'has version increased by 1' do
|
29
|
+
original_version = aggregate.version
|
30
|
+
aggregate.test_fire
|
31
|
+
|
32
|
+
expect(aggregate.version).to eq(original_version + 1)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'leaves source_version unchanged' do
|
36
|
+
original_source_version = aggregate.instance_variable_get(:@source_version)
|
37
|
+
aggregate.test_fire
|
38
|
+
|
39
|
+
expect(aggregate.instance_variable_get(:@source_version)).to eq original_source_version
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'calls #on_third_event' do
|
43
|
+
expect(aggregate).to receive(:on_third_event)
|
44
|
+
aggregate.test_fire
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#is_version_conflicted?' do
|
50
|
+
let(:state) { { :aggregate_id => aggregate_id, :events => unsorted_events } }
|
51
|
+
let(:loaded_aggregate) { aggregate.send(:load_from, state); aggregate; }
|
52
|
+
|
53
|
+
it 'returns true when supplied client side version does not match the server side persisted source_version' do
|
54
|
+
client_side_version = unsorted_events.size - 1
|
55
|
+
expect(loaded_aggregate.is_version_conflicted? client_side_version).to be_truthy
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'returns false when supplied client side version matches the server side persisted source_version' do
|
59
|
+
client_side_version = unsorted_events.size
|
60
|
+
expect(loaded_aggregate.is_version_conflicted? client_side_version).to be_falsy
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#get_changes' do
|
65
|
+
context 'after raising no event' do
|
66
|
+
it 'returns nil' do
|
67
|
+
expect(aggregate.send(:get_changes)).to be_nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'after raising 2 events' do
|
72
|
+
it 'returns proper change summary' do
|
73
|
+
aggregate.test_fire
|
74
|
+
aggregate.test_fire_ag
|
75
|
+
pending_changes = aggregate.send(:get_changes)
|
76
|
+
|
77
|
+
expect(pending_changes[:events].size).to eq(2)
|
78
|
+
expect(pending_changes[:events][0].version).to eq(1)
|
79
|
+
expect(pending_changes[:events][1].version).to eq(2)
|
80
|
+
expect(pending_changes[:aggregate_id]).to eq(aggregate.aggregate_id)
|
81
|
+
expect(pending_changes[:aggregate_type]).to eq(aggregate.class.name)
|
82
|
+
expect(pending_changes[:expecting_source_version]).to eq(0)
|
83
|
+
expect(pending_changes[:expecting_version]).to eq(2)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe '#load_from' do
|
89
|
+
let(:state) { { :aggregate_id => aggregate_id, :events => unsorted_events } }
|
90
|
+
let(:loaded_aggregate) { aggregate.send(:load_from, state); aggregate; }
|
91
|
+
|
92
|
+
context 'when loading events' do
|
93
|
+
after(:each) { aggregate.send(:load_from, state) }
|
94
|
+
|
95
|
+
it 'calls #on_first_event' do
|
96
|
+
expect(aggregate).to receive(:on_first_event)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'calls #on_second_event' do
|
100
|
+
expect(aggregate).to receive(:on_second_event)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'calls #on_first_event, #on_second_event in order' do
|
104
|
+
expect(aggregate).to receive(:on_first_event).ordered
|
105
|
+
expect(aggregate).to receive(:on_second_event).ordered
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'after events are loaded' do
|
110
|
+
it "has aggregate_id set to the events' aggregate_id" do
|
111
|
+
expect(loaded_aggregate.aggregate_id).to eq(aggregate_id)
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'has version set to the number of loaded events' do
|
115
|
+
expect(loaded_aggregate.version).to eq(unsorted_events.size)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'has source_version set to the number of loaded events' do
|
119
|
+
expect(loaded_aggregate.instance_variable_get(:@source_version)).to eq(unsorted_events.size)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|