Edit

Spring Cloud Azure support for Testcontainers

This article describes how to integrate Spring Cloud Azure with Testcontainers to write effective integration tests for your applications.

Testcontainer is an open-source framework for providing throwaway, lightweight instances of databases, message brokers, web browsers, or just about anything that can run in a Docker container. It integrates with JUnit, enabling you to write a test class that can start up a container before any of the tests run. Testcontainer is especially useful for writing integration tests that talk to a real backend service.

The spring-cloud-azure-testcontainers library now supports integration testing for the following Azure services:

Service connections

A service connection is a connection to any remote service. Spring Boot's autoconfiguration can consume the details of a service connection and use them to establish a connection to a remote service. When doing so, the connection details take precedence over any connection-related configuration properties.

When you use Testcontainers, you can automatically create connection details for a service running in a container by annotating the container field in the test class.

xxxContainerConnectionDetailsFactory classes are registered with spring.factories. These factories create a ConnectionDetails bean based on a specific Container subclass or the Docker image name.

The following table provides information about the connection details factory classes supported in the spring-cloud-azure-testcontainers JAR:

Connection details factory class Connection details bean
CosmosContainerConnectionDetailsFactory AzureCosmosConnectionDetails
StorageBlobContainerConnectionDetailsFactory AzureStorageBlobConnectionDetails
StorageQueueContainerConnectionDetailsFactory AzureStorageQueueConnectionDetails
EventHubsContainerConnectionDetailsFactory AzureEventHubsConnectionDetails
ServiceBusContainerConnectionDetailsFactory AzureServiceBusConnectionDetails

Set up dependencies

The following configuration sets up the required dependencies:

  
    7.4.0
  

  
    
      
        com.azure.spring
        spring-cloud-azure-dependencies
        ${version.spring.cloud.azure}
        pom
        import
      
    
  

  
    
      org.springframework.boot
      spring-boot-starter-test
      test
    
    
      org.testcontainers
      testcontainers-junit-jupiter
      test
    
    
      com.azure.spring
      spring-cloud-azure-testcontainers
      test
    
    
      com.azure.spring
      spring-cloud-azure-starter-cosmos
      test
    
  

Use Testcontainers

The following code example demonstrates the basic usage of Testcontainers:

@SpringBootTest(classes = CosmosTestcontainersTest.class)
@Testcontainers
@ExtendWith(SpringExtension.class)
@ImportAutoConfiguration(classes = { AzureGlobalPropertiesAutoConfiguration.class, AzureCosmosAutoConfiguration.class})
public class CosmosTestcontainersTest {

    @TempDir
    private static File tempFolder;

    @Autowired
    private CosmosClient client;

    @Container
    @ServiceConnection
    static CosmosDBEmulatorContainer cosmos = new CosmosDBEmulatorContainer(
        DockerImageName.parse("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest"))
                .waitingFor(Wait.forHttps("/_explorer/emulator.pem").forStatusCode(200).allowInsecure())
                .withStartupTimeout(Duration.ofMinutes(3));

    @BeforeAll
    public static void setup() throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException {
        Path keyStoreFile = new File(tempFolder, "azure-cosmos-emulator.keystore").toPath();
        KeyStore keyStore = cosmos.buildNewKeyStore();
        try (var out = Files.newOutputStream(keyStoreFile.toFile().toPath())) {
            keyStore.store(out, cosmos.getEmulatorKey().toCharArray());
        }

        System.setProperty("javax.net.ssl.trustStore", keyStoreFile.toString());
        System.setProperty("javax.net.ssl.trustStorePassword", cosmos.getEmulatorKey());
        System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");
    }

    @Test
    public void test() {
        CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists("Azure");
        assertThat(databaseResponse.getStatusCode()).isEqualTo(201);
        CosmosContainerResponse containerResponse = client
            .getDatabase("Azure")
            .createContainerIfNotExists("ServiceContainer", "/name");
        assertThat(containerResponse.getStatusCode()).isEqualTo(201);
    }

}

To use CosmosDBEmulatorContainer, you need to prepare a KeyStore for TLS/SSL. For more information, see Cosmos DB Azure Module in the Testcontainers documentation. With @ServiceConnection, this configuration enables Cosmos DB-related beans in the app to communicate with Cosmos DB running inside the Testcontainers-managed Docker container. This setup automatically defines an AzureCosmosConnectionDetails bean, which the Cosmos DB autoconfiguration then uses to override any connection-related configuration properties.

Samples

For more information, see the spring-cloud-azure-testcontainers examples.