Where to put calculations

Hi,

here is a simplified scenario, real life is a bit more complicated:

  • Project aggregate receives command RegisterActivity(from, to, sequence, volumeProduced).
  • Aggregate applies ActivityRegistered(from, to, sequence, volumeProduced).
  • Aggregate also applies SequenceProductionModified(sequence, newVolume).

Business rule: newVolume = sequenceVolume + volumeProduced.

The aggregate keeps a map of <sequence, sequenceVolume>.

The aggregate also has a handler that modifies it’s sequence volume map on a SequenceProductionModified event.

At first glance this seems fine. The registerActivity(…) method does the calculation and emits the events containing calculated values. I keep the business rule inside the aggregate root and the read model projector maps one-one sequence events to a report.

— Then it comes to testing.

Test first activity registration:

given().when(RegisterActivity).expect(ActivityRegistered, SequenceProductionModified) checks ok.

Test register two activities:

given(ActivityRegistered).when(RegisterActivity).expect(ActivityRegistered, SequenceProductionModified) doesn’t check ok because the test must add the derived event SequenceProductionModified to the given block for the state to be correct.

Is this way of coding the scenario ok, if not best practice, or am I missing something?

Geir

Hi Geir,

the test looks ok. The problem of 1 command that produces multiple events is a common one when it comes to testing. Usually, you only need to specify “relevant” events to the “given” state.

I recently added a method that allows you to specify commands in the “given” stage as well. That makes it easier in those scenarios. The command in the “when” stage uses the events generated by the commands in the “given” stage to reconstruct the aggregate.

Hope this helps,
Cheers,

Allard

Allard,

thanks for a quick answer (as always) !

The given command sounds perfect, then the test doesn’t need to know about intermediary derived events.

Geir