AggregateTestFixture

When I run the given, expected events through the aggregate, it works great but I want to extract from the Aggregate the internal properties, the summed up values.

The events apply logic to these and I wanted to verify that the values are calculated properly after the events have been applied?

MyAggregate …

private int demand;
private int locked;
private int supply;

Test …
FixtureConfiguration fixture = new AggregateTestFixture(MyAggregate.class);
fixture
.given()
.when(command)
.expectReturnValue(null)
.expectEvents(events));

//TODO: How to check the value of demand, locked, supply properties
}

Thanks,

Hi Gerard,

The recommendation is to validate the state of the aggregate through the emitted events and handling of subsequent commands. In other words: don’t assert the calculated values but rather assert the (altered) behaviour of the aggregate caused by the calculation.

E.g. assuming following handler exists:
@CommandHandler public void handle(ReservationComnmand command) { if (demand <= supply) { apply(new ReservedEvent(..)); } }

Then you would unit test this handler as such:

@Test public void testReservationRefused() { fixture.given(event1, event2, ...) // events needed to initialise variables 'demand' and 'supply' such that demand > supply .when(new ReservationCommand(aggregateId)) .expectNoEvents(); }

The unit test does not rely on how the aggregate state is represented. You can easily replace integers demand, locked and supply by BigInteger without having to change the unit test.

Regards,
Benoît

Thanks Benoit,
I like the way you did that for sure and will use it but after the events have applied, the state of the object needs to get published to an external source NOSQL database, the read-only DB. For testing I want to ensure the correct events fire but also the logic and state are correct.

The below code gives me 110% more confident but obviously uses reflection isn’t great.

@Test
public void shouldCreateAggregateAndRaiseLockedStockEvent() throws Exception {
    String sku = "305";

    fixture
            .given()
            .when(new StockItemLockCommand(sku, 6))
            .expectReturnValue(null)
            .expectEvents(new StockItemCreatedEvent(sku,0), new StockItemLockEvent(sku, 6));

    Field workingAggregateField = fixture.getClass().getDeclaredField("workingAggregate");
    workingAggregateField.setAccessible(true);
    StockItem stockItem =  ((EventSourcedAggregate<StockItem>) workingAggregateField.get(fixture)).getAggregateRoot();

    assertEquals("Stock Aggregate - Locked Stock Mismatch", 6, stockItem.getLocked());
}

Regards,
Gerry.

Hi Gerard/Benoît,

Your code seems to suggest you’re using a EventSourcingRepository,

but you’re saying you’re also storing the entire state of the aggregate in an ‘external NoSQL source’.

That thus sounds you’re using the Aggregate for both write and read usages,

whilst generally we suggest creating a separate read view which is populated through events.
That doesn’t mean it’s wrong though, in your use case it just might make a lot of sense to also store the aggregate state.

How are you storing the entire state of the aggregate next to publishing events?
Are you using your own Repository implementation?

What Benoît is suggesting is indeed the testing form we suggest to use for you aggregates.

Cheers,
Steven