Introduction
Testcontainers has released dedicated modules for Azure Event Hubs and Azure Service Bus emulators.
These modules greatly simplify the use of these emulators compared to the custom solutions I previously implemented using generic containers and docker compose in:
1. Using Azure Event Hubs Emulator as a Test Container
2. Using Azure Service Bus Emulator as a Test Container
In this article, I’ll show how to use these new modules in Spring Boot by applying the singleton containers pattern.
Singleton Containers Pattern
With the singleton containers pattern, containers are started only once and reused across all test classes.
This approach is especially valuable for Event Hubs and Service Bus emulators, as each depends on additional containers. Starting and stopping these dependencies for every test class—or worse, every individual test—would be highly inefficient and slow down the entire test suite.
In our setup, all required containers are started in a base test class, and all other test classes extend it. This ensures containers are initialized only once, while their configuration remains available everywhere.
We then inject the container connection properties into the Spring Boot application context using @DynamicPropertySource
, which lets us define Spring properties dynamically at runtime based on container output.
Using Event Hubs Module
Dependencies:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>azure</artifactId>
<version>1.21.3</version>
<scope>test</scope>
</dependency>
Base class (on GitHub):
abstract class AbstractIntegrationTest {
public static final String AZURITE_IMAGE = "mcr.microsoft.com/azure-storage/azurite:3.33.0";
public static final String EVENTHUBS_IMAGE = "mcr.microsoft.com/azure-messaging/eventhubs-emulator:2.0.1";
private static final Network network = Network.newNetwork();
private static final AzuriteContainer azurite = new AzuriteContainer(AZURITE_IMAGE)
.withNetwork(network);
private static final EventHubsEmulatorContainer emulator = new EventHubsEmulatorContainer(EVENTHUBS_IMAGE)
.acceptLicense()
.withNetwork(network)
.withConfig(MountableFile.forClasspathResource("eventhub-emulator-config.json"))
.withAzuriteContainer(azurite);
static {
azurite.start();
emulator.start();
}
@DynamicPropertySource
static void registerPgProperties(DynamicPropertyRegistry registry) {
registry.add("spring.cloud.azure.eventhubs.connection-string=", emulator::getConnectionString);
registry.add("spring.cloud.azure.eventhubs.processor.checkpoint-store.connection-string", azurite::getConnectionString);
registry.add("spring.cloud.azure.eventhubs.processor.checkpoint-store.endpoint", () -> String.format("http://localhost:%d/devstoreaccount1/", azurite.getMappedPort(10000)));
}
}
Using Service Bus Module
Dependencies:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>azure</artifactId>
<version>1.21.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>12.8.1.jre11</version>
<scope>test</scope>
</dependency>
Base class (on GitHub):
abstract class AbstractIntegrationTest {
public static final String SQL_SERVER_IMAGE = "mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04";
public static final String SERVICEBUS_IMAGE = "mcr.microsoft.com/azure-messaging/servicebus-emulator:1.1.2";
private static final Network network = Network.newNetwork();
public static MSSQLServerContainer<?> mssqlServerContainer = new MSSQLServerContainer<>(SQL_SERVER_IMAGE)
.acceptLicense()
.withPassword("yourStrong(!)Password")
.withCreateContainerCmdModifier(cmd -> cmd.getHostConfig().withCapAdd(Capability.SYS_PTRACE))
.withNetwork(network);
public static ServiceBusEmulatorContainer emulator = new ServiceBusEmulatorContainer(SERVICEBUS_IMAGE)
.acceptLicense()
.withConfig(MountableFile.forClasspathResource("/servicebus-emulator-config.json"))
.withNetwork(network)
.withMsSqlServerContainer(mssqlServerContainer);
static {
mssqlServerContainer.start();
emulator.start();
}
@DynamicPropertySource
static void registerPgProperties(DynamicPropertyRegistry registry) {
registry.add("spring.cloud.azure.servicebus.connection-string", emulator::getConnectionString);
registry.add("emulator-ampq-port", emulator::getFirstMappedPort);
}
}
Summary
Use Testcontainers’ Azure Event Hubs and Service Bus modules with the singleton containers pattern to speed up Spring Boot integration tests.
Start emulators once in a base test class, inject their connection strings with @DynamicPropertySource
, and extend that class in your tests for fast, consistent, and fully local testing.
For examples of extending and using the base class visit the GitHub repository: azure-testcontainers-in-spring-boot