Test Fails with DataJpaTest Annotation

I am working on writing some tests for an entity class to make sure that the column restrictions I’ve placed on the properties of that entity are enforced. This is to make sure that these restrictions are only change intentionally.

Below is the test thus far:

@DataJpaTest
@ActiveProfiles("test")
class AccountLookupEntityIntegrationTest {

    @Autowired
    private TestEntityManager testEntityManager;

    private AccountLookupEntity accountLookupEntity;

    private static final String TEST_ACCOUNT_ID = "test-account-id";
    private static final String TEST_EMAIL = "test@test.com";
    @BeforeEach
    void setup() {
        accountLookupEntity = new AccountLookupEntity();
        accountLookupEntity.setAccountId(TEST_ACCOUNT_ID);
        accountLookupEntity.setEmail(TEST_EMAIL);
    }

    @Test
    void testAccountLookupEntity_whenValidAccountDetailsProvided_shouldReturnStoredAccountDetails() {
        // Act
        AccountLookupEntity storedAccountLookupEntity = testEntityManager.persistAndFlush(accountLookupEntity);

        // Assert
        assertEquals(accountLookupEntity.getAccountId(), storedAccountLookupEntity.getAccountId(), "AccountIds should match");
        assertEquals(accountLookupEntity.getEmail(), storedAccountLookupEntity.getEmail(), "Emails should match");
    }
}

And here is the application-test.yml file that holds the config for the h2 database being used for the test:

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password: password
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect

If necessary you can see all the code for the repository here

So the root of my issue I believe is summarized in this log statement:

{"timestamp":"2024-10-22-T23:25:00,668Z","level":"ERROR","logger":"org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter","message":"\n\n***************************\nAPPLICATION FAILED TO START\n***************************\n\nDescription:\n\nParameter 1 of method registerAccountCommandInterceptors in loyalty.service.LoyaltyCommandApiApplication required a bean of type 'org.axonframework.commandhandling.CommandBus' that could not be found.\n\n\nAction:\n\nConsider defining a bean of type 'org.axonframework.commandhandling.CommandBus' in your configuration.\n"}

Which to me points to the interceptor setups that I do in my spring application class:

@EnableDiscoveryClient
@EnableScheduling
@SpringBootApplication
public class LoyaltyCommandApiApplication {

	public static void main(String[] args) {
		SpringApplication.run(LoyaltyCommandApiApplication.class, args);
	}

	@Autowired
	public void registerAccountCommandInterceptors(ApplicationContext context, CommandBus commandBus) {
		commandBus.registerDispatchInterceptor(
				context.getBean(ValidateCommandInterceptor.class)
		);
		commandBus.registerDispatchInterceptor(
				context.getBean(AccountCommandsInterceptor.class)
		);
		commandBus.registerDispatchInterceptor(
				context.getBean(BusinessCommandsInterceptor.class)
		);
		commandBus.registerDispatchInterceptor(
				context.getBean(LoyaltyBankCommandsInterceptor.class)
		);
		commandBus.registerDispatchInterceptor(
				context.getBean(TransactionCommandsInterceptor.class)
		);
	}

	@Autowired
	public void configure(EventProcessingConfigurer configurer) {
		// TODO: Save group strings to constants
		configurer.registerListenerInvocationErrorHandler("account-lookup-group",
				configuration -> new LoyaltyServiceEventsErrorHandler());
		configurer.registerListenerInvocationErrorHandler("business-lookup-group",
				configuration -> new LoyaltyServiceEventsErrorHandler());
		configurer.registerListenerInvocationErrorHandler("loyalty-bank-lookup-group",
				configuration -> new LoyaltyServiceEventsErrorHandler());
		configurer.registerListenerInvocationErrorHandler("redemption-tracker-group",
				configuration -> new LoyaltyServiceEventsErrorHandler());
		configurer.registerListenerInvocationErrorHandler("expiration-tracker-group",
				configuration -> new LoyaltyServiceEventsErrorHandler());

	}
}

But I am not entirely sure that this is correct. I understand that this is somewhat of a vague question and maybe this is more of a spring issue than it is an Axon related one, but I am currently at a loss for trying to determine why the @DataJpaTest annotation doesn’t work. If I use @SpringTest then the test will sort of run, but the TestEntityManager doesn’t work and ideally I would like to keep the application context of these tests as small as possible.

If anyone has any suggestions as to how to properly configure my environment to be able to use the @DataJpaTest annotation for testing these entities it would be greatly appreciated.

And duck debugging strikes again!

After writing out the question for this post, I thought about the issue being related to my interceptor and event handler initialization directly in my spring application class. This lead me to the idea of moving those initializer methods to a separate configuration class.

@Configuration
public class AxonConfig {

    @Autowired
    public void registerAccountCommandInterceptors(ApplicationContext context, CommandBus commandBus) {
        commandBus.registerDispatchInterceptor(
                context.getBean(ValidateCommandInterceptor.class)
        );
        commandBus.registerDispatchInterceptor(
                context.getBean(AccountCommandsInterceptor.class)
        );
        commandBus.registerDispatchInterceptor(
                context.getBean(BusinessCommandsInterceptor.class)
        );
        commandBus.registerDispatchInterceptor(
                context.getBean(LoyaltyBankCommandsInterceptor.class)
        );
        commandBus.registerDispatchInterceptor(
                context.getBean(TransactionCommandsInterceptor.class)
        );
    }

    @Autowired
    public void configure(EventProcessingConfigurer configurer) {
        // TODO: Save group strings to constants
        configurer.registerListenerInvocationErrorHandler("account-lookup-group",
                configuration -> new LoyaltyServiceEventsErrorHandler());
        configurer.registerListenerInvocationErrorHandler("business-lookup-group",
                configuration -> new LoyaltyServiceEventsErrorHandler());
        configurer.registerListenerInvocationErrorHandler("loyalty-bank-lookup-group",
                configuration -> new LoyaltyServiceEventsErrorHandler());
        configurer.registerListenerInvocationErrorHandler("redemption-tracker-group",
                configuration -> new LoyaltyServiceEventsErrorHandler());
        configurer.registerListenerInvocationErrorHandler("expiration-tracker-group",
                configuration -> new LoyaltyServiceEventsErrorHandler());

    }
}

Then I set the test using @DataJpaTest annotation to exclude the configuration class with the following annotation applied to the test class:

@ImportAutoConfiguration(exclude = {AxonConfig.class})

And now I am able to use the @DataJpaTest annotation with the TestEntityManager.

I hope this helps anyone else who may encounter this issue in the future.

1 Like