how to test that published event in AR are properly consumed by @EventHandler in AR

Hi,

I’ve some concerns about @EventHandler in AR.
I know that Axon Fixtures makes testing easy and readable but they don’t test the persistence of changes that we are applying in @EventHandler sections.
Consider the example from axon-trader example app:
In module orders we have class Portfolio that publishes the CashReservedEvent. There are some business rules that are not allow to reserve cash if amountOfMoney >= amountToReserve. We can see that here:

public void reserveMoney(TransactionId transactionIdentifier, long amountToReserve) {
    if (amountOfMoney >= amountToReserve) {
        apply(new CashReservedEvent(portfolioId, transactionIdentifier, amountToReserve));
    } else {
        apply(new CashReservationRejectedEvent(portfolioId, transactionIdentifier, amountToReserve));
    }
}

And according to that there is related @EventHandler

@EventHandler
public void onMoneyReservedFromPortfolio(CashReservedEvent event) {
    amountOfMoney -= event.getAmountToReserve();
    reservedAmountOfMoney += event.getAmountToReserve();
}

And that looks quite neat and clean. All test are working. But when I change the @EventHandler implementation to:


@EventHandler
public void onMoneyReservedFromPortfolio(CashReservedEvent event) {
    amountOfMoney += event.getAmountToReserve();
    reservedAmountOfMoney -= event.getAmountToReserve();
}

I violate business rule that **amnountOfMoney** cannot be less than zero. But all tests still works.

My question here is how to handle with that problem? Lastly I simply missed to implement the **@EventHandler** and was wondering why my changes are not applied to the AR ;)

Only solution that came to my head is to test such case:

given:
 20 amount of money
 10 as amount to reserve
when:
 15 as amount to reserve 
then:
 expect CashReservationRejectedEvent

Here the simulation is quite easy, but I can imagine more complex business rules that will be harder to simulate. 
Or simply forget to implement the proper **@EventHandler** (I commented out the **@EventHandler** that handles the **CashReservedEvent** and all test are still green)

Does anyone have same or similar problem with that? 

m.
 

`

`

Hi Mateusz,

To test whether you’re violating the business rule if you’re allowed to reserve money in the Aggregate, you’d probably need to do a follow up tests which tries to reserve even more money.
On that follow up test, you’d then expect that the reserve shouldn’t be allowed, because the amountOfMoney is to low.
But if you do receive a CashReservedEvent, you know something’s wrong in the event handler.

By thus adding that test, you wouldn’t have to have the ability to check the state of your aggregate; since the events flowing out of the aggregate tell you if you’re doing something wrong or not.
So, you already answered your question yourself in the last bit, were you give the example of that you have an amount of 20, reserve 10 and then try to reserve 15, where you expect that it’s rejected.

Additionally, it’s best practice to use the @EventSourcingHandler annotation for event handling function in your aggregate.

Hope this helps :slight_smile:

Cheers,

Steven van Beelen

Hi Steven,

thanks for the reply. I know that it resolves some cases, but for me it’s still some kind of a workaround.

Suppose you developed a lot of stuff, and you simply forget to implement the @EventSourcingHandler method. But tests with fixture works just fine. And BUM bug on production ;).

I think that the main problem is that using Axon Framework Fixtures we are not explicitly testing the aggregates but rather the ES flow.
For me the best thing will be to have the ability to really apply the events in when section. And instead of only validating that the events has occurred I would like to check also the actual aggregate state after handling the command.

Maybe someone has the solution for that?

W dniu czwartek, 9 marca 2017 10:57:14 UTC+1 użytkownik Steven van Beelen napisał:

Hi Mateusz,

this discussion pops up every now and then. When modeled correctly, the state of an aggregate at any point in time is completely irrelevant. The only thing that really matters is the events that it published under specific conditions.

In your example, with the bug on production, it’s not the test that didn’t verify the end state that failed. It’s the lack of a test that acts upon the state the aggregate is supposed to have that fails!

So instead of wanting to check the state of given(A, B) when © expect (D), do a, given(A, B, D) when (E) expect (F). If your EventSourcingHandler for D is missing or incorrect, that test should fail.

Cheers,

Allard