AxonServer in tests

Hello Axon community,

I’m trying to set up an integration (kind of) testing environment where I’ll be able to test the self-contained component through the anticorruption layer (REST API). I say integration because it’s not the full-blown API testing that runs against the real, similarly full-blown environment (for ex: k8s cluster that includes a relational database for query model and etc.), but rather idea is to include such tests in the component’s build phase (possibly with mocking out some of the irrelevant aspects) to get the feedback as early as possible.

I’m challenged by the situation where I should decide whether or not to use the real AxonServer in such tests. My initial idea was to go for this approach, cause I wanted to minimize the differences between test and real environments. But then I found that there’s no easy way (known to me) to programmatically control the lifecycle of AxonServer. I’d like to avoid calling docker or java commands from the test.

Then I decided to create a specialized Axon configuration for tests that configures in-memory event storage, and simple query/command buses
Screen Shot 2020-08-10 at 23.33.40.png

This seemed to work out pretty well until I reached the case that involves the handling of deleted aggregate root. The problem is that this error is reported differently by CommandGateway.sendAndWait depending on the environment. CommandExecutionException (as part of the CommandGateway API) is thrown in the real environment, and AggregateNotFoundException - in test env (because of the config in use).

I believe there must be a way to work around with such differences, for example by implementing custom MessageHandlerInterceptor as suggested here (I haven’t tried yet). But even if I manage to do so, I started to revisit the topic of using real AxonServer in tests. Is there a way to do so? i.e. to have a programmable variant of AxonServer that implements Axon Server API, but is relatively lightweight (for example, uses in-memory event store still).

Hi Beka,
We are using testcontainers (https://www.testcontainers.org/) in our integration tests to spin up a docker container with Axon Server from the testcase. I know this is still using docker, but you control the container from Java. Creating a docker container with testcontainers would be something like:

container = new GenericContainer(“axoniq/axonserver”)
.withExposedPorts(8024, 8124)
.waitingFor(Wait.forHttp("/actuator/info").forPort(8024))
.withStartupTimeout(Duration.ofSeconds(WAIT_IN_SECONDS));

Note that testcontainers maps exposed ports to random ports, so in the AxonServerConfiguration you need to set the “servers” property to “localhost:” + container.getMappedPort(8124).

I hope this helps,

Marc

Hi Marc,

I never thought about such a possibility, this is exactly why asking for help is never a bad idea!
Thanks for the tip, I gave it a try and it seems to be working well!

Kind regards,
Beka