Search code examples
c#.netazure-cosmosdbtestcontainers

TestContainers.CosmosDB always gets stuck whenever making any CosmosClient API call


I am setting-up TestContainers.CosmosDB for my integration tests. Below is the code I used for running the CosmosDB emulator via docker image.

var cosmosDb = new CosmosDbBuilder()
  .WithImage("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest")
  .Build();
await cosmosDb.StartAsync();

Next is the code block I am using to connect to the running instance. But the call to create the database never returns - last line. While running the code, I can browse the CosmosDB explorer and see that the DB instance has spun-up locally but I am not able to interact with it via CosmosClient. How can I use CosmosClient to interact with the TestContainer instance ? I am running Linux containers on Windows machine. I have published this code here - https://github.com/riteshksriv/ConsoleAppCosmosDB

var clientOptions = new CosmosClientOptions
{
  ConnectionMode = ConnectionMode.Gateway,
  HttpClientFactory = () =>
  {
    HttpMessageHandler httpMessageHandler = new HttpClientHandler()
    {
      ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
    };
    return new HttpClient(httpMessageHandler);
  }
};
var cosmosClient = new CosmosClient(connectionString, clientOptions);
var dbResponse = await cosmosClient.CreateDatabaseIfNotExistsAsync("MyDatabase");

Solution

  • I believe this is an issue with the implementation of the Cosmos DB client. I reviewed the history but could not quickly find all the details.

    The Testcontainers for .NET Cosmos DB Emulator module includes a preconfigured HTTP client. This client rewrites the requests to the currently running Cosmos DB Emulator instance. To establish a connection, you will need to either configure the HTTP client yourself or use the provided module's client:

    using var httpClient = _cosmosDbContainer.HttpClient;
    
    var cosmosClientOptions = new CosmosClientOptions();
    cosmosClientOptions.ConnectionMode = ConnectionMode.Gateway;
    cosmosClientOptions.HttpClientFactory = () => httpClient;
    
    using var cosmosClient = new CosmosClient(_cosmosDbContainer.GetConnectionString(), cosmosClientOptions);
    

    Just an FYI: There is no need to fall back to HTTP. To support HTTPS, we can extract the certificate from the container and configure the HTTP client accordingly. However, this feature has not yet been implemented in the Testcontainers for .NET Cosmos DB Emulator module.