Dustin
Dustin

Reputation: 892

Test Axon aggregate's behaviour with non-aggregate events

I'm trying to ensure an aggregate field is unique on creation. I'm trying to handle the eventually consistency of the projections by using the following flow:

  1. Command creates a new aggregate
  2. Aggregate issues creation event
  3. Event handler attempts to materialize the projection and if there is a uniqueness violation, it emits a UniqueConstraintViolationEvent
  4. Aggregate consumes this event and marks itself as deleted

I'm trying to use the AggregateTestFixture to test this, but it doesn't appear to allow you to preform any assertions without issuing a command (whenThenTimeElapses seems to allow assertions, but I get a NPE when asserting the aggregate has been deleted). Is there a way to use the test fixture for this case, or is it not designed to account for non-aggregate events. If not, is there another way to verify that the aggregate has been removed?

I'm not confident that this is actually the correct approach. I've also considered dispatching a command in (3) or using a saga to manage the interaction. If I dispatch a command instead of an event, it seems to simply force me to write more boilerplate to emit the UniqueConstraintViolationEvent from the aggregate. Likewise, if I use a saga to model this interaction, I'm unsure how to end the saga's lifecycle without having the projection materializer emit a success event that the saga consumes.

Upvotes: 1

Views: 424

Answers (1)

Steven
Steven

Reputation: 7275

You are looking at a Set Based Validation scenario, which is a little more cumbersome when dealing with a CQRS system. This blog explains some of your options nicely I feel, thus I'd pick and choose from there.

As a form of guideline, note that the Aggregate guards it's own consistency boundary. Extending that boundary by asserting uniqueness among an entire set of Aggregate is thus not desirable. Simply put, not a single Aggregate instance's problem.

Hence, I would perform this uniqueness check prior to issuing the command, by consulting a lightweight query model containing the desired constraint.

Upvotes: 1

Related Questions