May 28, 2018

In my previous blog post about Axon, I showed how to create a simple application that uses event sourcing. In the end, you could call a REST API and test the application manually. I completely left out automated testing, even though I’m a big fan of Test-Driven Development. This was on purpose because I wanted to concentrate on the absolute basics. This time I wanted to show how to test applications with Axon.

As in the previous blog post, you can have a look at the complete project on GitHub: https://github.com/jd1/spring-boot-axon

JUnit5

I will write all the tests with JUnit 5. To support it you have to add JUnit 5 to the pom.xml and exclude the old JUnit:

There are a few changes between JUnit4 and JUnit 5. If you want to know more about it, you can read the official user guide.

Testing the aggregate

The BankAccount from my previous post is a simple aggregate which contains methods to react to events. You can use these methods to apply some events and in the end, verify the state of the aggregate, in this case, the account balance:

This test modifies the state of the aggregate without any additional framework (except Junit). It does not even call Axon specific code. This way of testing works as long as you don’t want to test commands. If you look into the implementation of e.g. BankAccount.on(DepositMoneyCommand), you will see that it calls  AggregateLifecycle.apply(new MoneyDepositedEvent(id, amount)); to publish an event. This will fail because Axon isn’t aware of the aggregate and cannot retrieve its lifecycle.

Axon Test Fixture

To test the command handling components Axon provides a test fixture. You can add it to your pom and start testing:

The test fixture provides an API where you define a test scenario with:

  • the events that already happened
  • the command you want to execute
  • the events or exception you expect

Setup

Before you write the first test you need to instantiate the test fixture with the aggregate class that you want to test:

No prerequisites

A simple test without any events in the past can look like this:

As you can see, the test has no prerequisites, it’s like working on an empty database. when(…) sends a command,  in this case, to create a new bank account. Then you verify that everything is successful and the expected AccountCreatedEvent is emitted.

With previous events

If the test requires a certain state of an aggregate, i. e. the aggregate has already processed some command (which lead to events), you define one or more events as given. The state of the aggregate is then built upon these events.

Exceptions

Of course, testing the happy path is not everything, you should also test commands that lead to exceptions. Instead of expectSuccessfulHandlerExecution() you call expectException(…):

In this case, the Axon Framework prevents an aggregate from being created twice. The same works if you try to send a command for an aggregate that does not exist. As a result, Axon will throw an AggregateNotFoundException:

But you can also test your own exceptions, e.g. if you try to get money from an account with an insufficient balance:

 

Conclusion

With little effort, and completely without Axon dependencies, it is possible to test the event processing of a single aggregate. If you want to go further and test commands, you can use the Axon Test Fixture. It provides a fluent API, which allows writing tests that are easy to read. You can set up an aggregate in the wanted state, apply new commands and verify the result. With this knowledge, you should be able to effectively test your event sourcing application and prevent bugs.

Leave a Comment

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close