Axon Test Create Aggregate State

I’m already using the AggregateTestFixture to test my aggregates and looking for a similar approach to test non-aggregate units for whom I need a specific aggregate state. For this I have some predefined commands in my testsuite and would like to reuse this command objects. Is there a way to prepare an aggregate with a specific state by applying comands, so that the events are applied on an aggregate automatically within the unit test environment?

Hi Viktor,
sorry but I didn’t fully understood your scenario.
I will try to give you couple of advice anyhow: test framework does not provide a way to test non-aggregate units out of the box (that’s why it’s called AggregateTestFixture).
Said so, the given method of AggregateTestFixture accept a list of commands that will be handled by the aggregate and will prepare it to a specific state. You can have a look into the ref guide example https://docs.axoniq.io/reference-guide/implementing-domain-logic/command-handling/testing#command-model-testing and to this block of code below.

@Test
public void testRedeemCardCommand() {
fixture.given(new CardIssuedEvent(“cardId”, 100),
new CardIssuedEvent(“cardId”, 200))
.when(new RedeemCardCommand(“cardId”, “transactionId”, 20))
.expectSuccessfulHandlerExecution()
.expectEvents(new CardRedeemedEvent(“cardId”, “transactionId”, 20));

If your use case include a call to an external entity, such as a @Repository for example, the framework gives you the possibility to inject a mock into the text fixture using registerInjectableResource() method.

private final YourRepository aRepository = mock(YourRepository.class);
private AggregateTestFixture testFixture;

@BeforeEach
void setUp() {
testFixture = new AggregateTestFixture<>(YourAggregateClass.class);
testFixture.registerInjectableResource(aRepository);

when(aRepository.findSomething(…)).thenReturn(aResult);
}

Hope that I said something useful for you.
If not, please describe your use case with some piece of code attached, so I can help you out in a more precise way.

Corrado.

If you want commands to define the “given” state, then you can use the givenCommands() method on the fixture.

Hi Corrado,

big thanks for the quick response. I will try to elaborate my scenario. I am testing the aggregates in the way you described it. For some commands I am using some predefined command objects in my test suite, to reuse especially the bigger ones, like initial commands which carry a lot of base data.
For example:

def “customer is created”() {
def createCustomerCommand = CustomerProvider.createCustomerCommand()

expect:
fixture.givenCommands()
.when(createCustomerCommand)
.expectSuccessfulHandlerExecution()
.expectEvents(CustomerCreatedEvent.of(createCustomerCommand.customerId(), createCustomerCommand.billingAddress()))
}

While the CustomerProvider implemented some factory methods within the test suite, to hide the unnecessary boiler plate code from the test like the billing address. Now I would like to reuse that test data in other tests. For example, to test a service which interacts with an external resource.

public InvoiceExternalId createExternalInvoice(final InvoiceCreatedEvent event) {

    Customer customer = customerSource.load(event.customerId());
InvoiceCreateRequest createRequest = invoiceMapper.map(event, customer.externalId());

    ResourceCreateResult result = api.createInvoice(true, createRequest).block();

    return InvoiceExternalId.*of*(result.getId());
}

To unit test this method, I would mock the customerSource to return a customer, which is required in a specific state. Of course, I could create events and apply them on the customer aggregate, but this will lead to more boilerplate code within the test suite, which already implemented by the command test objects.

I hope that it is more understandable and makes sense or am I on a wrong path?

Best Regards,
Viktor

Hi Viktor,
sorry for the late reply. Hope you already solved your issue.

I understand your use case: If we talk on aggregate testing I will personally set up every test case scenario applying a list of Events to the testFixture to bring the aggregate status to a certain scenario. This smells like boiler plate, but it will also verify that a certain command is really handled right after a list of events that were applied at your aggregate. Mock an aggregate status looks not so clean for a solution, if you ask me.

Instead the unit test of the utility method createExternalInvoice I think it’s fine to mock the Customer returned by customerSource. But it depends on your code, honestly it’s too hard to suggest a path here.

Please take a look also at fixture.givenNoPriorActivity(), that can be helpful in your code .

Hope this help,
Corrado.