Issue with test in Axon 2

My situation:

public interface MyAggregate extends EventSourcedAggregateRoot {

@CommandHandler
void handle(MyCommand command);

}

public class MyAggregateImpl extends AbstractAnnotatedAggregateRoot implements MyAggregate {

@Override
public void handle(MyCommand command)
//do stuff
}

}

Tests are done using: FixtureConfiguration fixture = Fixtures.newGivenWhenThenFixture(MyAggregateImpl.class);
When testing MyCommand, I get a NoHandlerForCommandException. At runtime it works.

I’m simplifying the situation a bit, so let me know if you need any more info.

Hi Jeroen,

I am surprised that it works at runtime, to be honest. The test fixture and runtime components use the same mechanism to register command handlers from aggregates. This mechanism doesn’t evaluate annotations placed on interfaces (yet). This means that you must put the @CommandHandler annotation on the declaration of the handle() method in your MyAggregateImpl.

Cheers,

Allard

Hi Allard,

Any idea when this feature will be added to Axon 2 (it worked in Axon 1.4)?

I just double-checked and the handlers from the interface definitely get subscribed at runtime. One thing that is different at runtime compared to test, is that i use an AbstractAggregateFactory (there are multiple implementations of MyAggregate).

Maybe this triggers the interface to be scanned for command handlers?

Hi Jeroen,

Now I understand why it works at runtime. The adapter inspects the class that you pass as parameter, and the superclasses of that class. At runtime, you pass the interface class. In the test, the implementation.

Fixing this isn’t too hard. I can schedule it for 2.0.3.

Cheers,

Allard

That’s what I thought. Great, I hope this makes it to 2.0.3.

Also: I wrote that this worked in Axon 1.4, but that’s not true actually, because in that test we also passed the interface.

As a workaround, you can explicitly define an AggregateCommandHandlerAdapter that uses the interface in the Fixture.

Could you explain how to go about that?

Hi Jeroen,

I thought something like “registerCommandHandler(new AggregateAnnotationCommandHandler(MyAggregateInterface.class))” would do, but that doesn’t work.

The best is to mimic your production scenario:
fixture = newGivenWhenThenFixture(MyInterface.class);
fixture.registerAggregateFactory(new GenericAggregateFactory(MyAggregate.class))

This way, the fixture will inspect the interface for annotations, but create instances of the MyAggregate class.
2.0.3-SNAPSHOT contains a fix that will also inspect annotations declared on the interface.

Cheers,

Allard

Just tried this:

fixture = newGivenWhenThenFixture(MyInterface.class);
fixture.registerAggregateFactory(new GenericAggregateFactory(MyAggregate.class))

But it doesn’t work: IllegalArgumentException: Given aggregateType may not be abstract. I think on line 1 a GenericAggregateFactory(MyInterface.class) is constructed, which is not allowed.

Anyway, 2.0.3-SNAPSHOT seems to fix the issue, thanks.