Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ddcbe02
feat: Update CosmosDb image to vnext-preview version
NelsonBN Dec 31, 2024
4827b45
Improved API port mapping and reintroduced the rewritten HTTP client.
NelsonBN Dec 31, 2024
b991265
Remove unused namespaces from CosmosDbBuilder
NelsonBN Dec 31, 2024
53f35d8
Merge branch 'develop' into feature/update-cosmosdb-image-version
NelsonBN Jan 2, 2025
01bc2f9
Merge branch 'develop' into feature/update-cosmosdb-image-version
NelsonBN Jan 9, 2025
87e978e
fix: Removed dependency on Cosmos Client and improved Cosmos wait str…
NelsonBN Jan 9, 2025
b620a7d
Merge branch 'develop' into feature/update-cosmosdb-image-version
NelsonBN Jan 16, 2025
370afa2
Merge branch 'develop' into feature/update-cosmosdb-image-version
NelsonBN Jan 23, 2025
11c8080
Merge branch 'develop' into feature/update-cosmosdb-image-version
NelsonBN Mar 18, 2025
d20b996
Merge branch 'develop' into feature/update-cosmosdb-image-version
NelsonBN May 9, 2025
1763e5d
merge: branch 'main' into feature/update-cosmosdb-image-version
NelsonBN Feb 28, 2026
16aa1d8
fix(cosmosdb): improved health check by using the /alive endpoint
NelsonBN Feb 28, 2026
e1cbdff
Merge branch 'develop' into feature/update-cosmosdb-image-version
NelsonBN Feb 28, 2026
85e55ce
chore: improvements to some technical debts
NelsonBN Feb 28, 2026
a30b54a
chore: improvements to some technical debts
NelsonBN Feb 28, 2026
dd50e95
refactor(cosmosdb): simplify health check implementation in WaitUntil…
NelsonBN Mar 1, 2026
6cf4a20
Merge branch 'develop' into feature/update-cosmosdb-image-version
NelsonBN Mar 6, 2026
bd60777
Merge branch 'develop' into feature/update-cosmosdb-image-version
NelsonBN Mar 6, 2026
17d9806
chore: Align configuration with TC for Go
HofmeisterAn Mar 7, 2026
5f3c18b
Merge branch 'develop' into feature/update-cosmosdb-image-version
HofmeisterAn Mar 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 4 additions & 32 deletions src/Testcontainers.CosmosDb/CosmosDbBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Testcontainers.CosmosDb;
[PublicAPI]
public sealed class CosmosDbBuilder : ContainerBuilder<CosmosDbBuilder, CosmosDbContainer, CosmosDbConfiguration>
{
public const string CosmosDbImage = "mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest";
public const string CosmosDbImage = "mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview";
Comment thread
NelsonBN marked this conversation as resolved.
Comment thread
HofmeisterAn marked this conversation as resolved.

public const ushort CosmosDbPort = 8081;

Expand Down Expand Up @@ -44,8 +44,9 @@ protected override CosmosDbBuilder Init()
{
return base.Init()
.WithImage(CosmosDbImage)
.WithEnvironment("ENABLE_EXPLORER", "false")
.WithPortBinding(CosmosDbPort, true)
.WithWaitStrategy(Wait.ForUnixContainer().AddCustomWaitStrategy(new WaitUntil()));
.WithWaitStrategy(Wait.ForUnixContainer().UntilHttpRequestIsSucceeded(request => request.ForPort(CosmosDbPort)));
}

/// <inheritdoc />
Expand All @@ -65,33 +66,4 @@ protected override CosmosDbBuilder Merge(CosmosDbConfiguration oldValue, CosmosD
{
return new CosmosDbBuilder(new CosmosDbConfiguration(oldValue, newValue));
}

/// <inheritdoc cref="IWaitUntil" />
private sealed class WaitUntil : IWaitUntil
{
/// <inheritdoc />
public async Task<bool> UntilAsync(IContainer container)
{
// CosmosDB's preconfigured HTTP client will redirect the request to the container.
const string requestUri = "https://localhost/_explorer/emulator.pem";

var httpClient = ((CosmosDbContainer)container).HttpClient;

try
{
using var httpResponse = await httpClient.GetAsync(requestUri)
.ConfigureAwait(false);

return httpResponse.IsSuccessStatusCode;
}
catch (Exception)
{
return false;
}
finally
{
httpClient.Dispose();
}
}
}
}
}
22 changes: 18 additions & 4 deletions src/Testcontainers.CosmosDb/CosmosDbContainer.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Microsoft.Azure.Cosmos;

namespace Testcontainers.CosmosDb;

/// <inheritdoc cref="DockerContainer" />
Expand All @@ -20,11 +22,23 @@ public CosmosDbContainer(CosmosDbConfiguration configuration)
public string GetConnectionString()
{
var properties = new Dictionary<string, string>();
properties.Add("AccountEndpoint", new UriBuilder(Uri.UriSchemeHttps, Hostname, GetMappedPublicPort(CosmosDbBuilder.CosmosDbPort)).ToString());
properties.Add("AccountEndpoint", new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(CosmosDbBuilder.CosmosDbPort)).ToString());
properties.Add("AccountKey", CosmosDbBuilder.DefaultAccountKey);
return string.Join(";", properties.Select(property => string.Join("=", property.Key, property.Value)));
}

/// <summary>
/// Gets a configured cosmos client with connection mode set to Gateway.
/// </summary>
public CosmosClient CosmosClient
=> new CosmosClient(
GetConnectionString(),
new()
{
ConnectionMode = ConnectionMode.Gateway,
HttpClientFactory = () => new(new UriRewriter(Hostname, GetMappedPublicPort(CosmosDbBuilder.CosmosDbPort)))
Comment thread
NelsonBN marked this conversation as resolved.
Outdated
});

/// <summary>
/// Gets a configured HTTP message handler that automatically trusts the CosmosDb Emulator's certificate.
/// </summary>
Expand All @@ -50,7 +64,7 @@ private sealed class UriRewriter : DelegatingHandler
/// <param name="hostname">The target hostname.</param>
/// <param name="port">The target port.</param>
public UriRewriter(string hostname, ushort port)
: base(new HttpClientHandler { ServerCertificateCustomValidationCallback = (_, _, _, _) => true })
: base(new HttpClientHandler())
{
_hostname = hostname;
_port = port;
Expand All @@ -59,8 +73,8 @@ public UriRewriter(string hostname, ushort port)
/// <inheritdoc />
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.RequestUri = new UriBuilder(Uri.UriSchemeHttps, _hostname, _port, request.RequestUri.PathAndQuery).Uri;
request.RequestUri = new UriBuilder(Uri.UriSchemeHttp, _hostname, _port, request.RequestUri.PathAndQuery).Uri;
return base.SendAsync(request, cancellationToken);
}
}
}
}
3 changes: 2 additions & 1 deletion src/Testcontainers.CosmosDb/Testcontainers.CosmosDb.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" VersionOverride="2023.3.0" PrivateAssets="All"/>
<PackageReference Include="Microsoft.Azure.Cosmos"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Testcontainers/Testcontainers.csproj"/>
</ItemGroup>
</Project>
</Project>
62 changes: 50 additions & 12 deletions tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace Testcontainers.CosmosDb;
using System;
using System.Linq;

namespace Testcontainers.CosmosDb.Tests;

public sealed class CosmosDbContainerTest : IAsyncLifetime
{
Expand All @@ -14,24 +17,59 @@ public Task DisposeAsync()
return _cosmosDbContainer.DisposeAsync().AsTask();
}

[Fact(Skip = "The Cosmos DB Linux Emulator Docker image does not run on Microsoft's CI environment (GitHub, Azure DevOps).")] // https://github.com/Azure/azure-cosmos-db-emulator-docker/issues/45.
[Fact]
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
public async Task CreateDatabaseAndContainerSuccessful()
{
// Given
using var cosmosClient = _cosmosDbContainer.CosmosClient;


// When
var database = (await cosmosClient.CreateDatabaseIfNotExistsAsync("fakedb")).Database;
await database.CreateContainerIfNotExistsAsync("fakecontainer", "/id");
var databaseProperties = (await cosmosClient.GetDatabaseQueryIterator<DatabaseProperties>().ReadNextAsync()).First();


// Then
Assert.Equal("fakedb", databaseProperties.Id);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}


[Fact]
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
public async Task AccountPropertiesIdReturnsLocalhost()
public async Task RetrieveItemCreated()
{
// Given
using var httpClient = _cosmosDbContainer.HttpClient;
using var cosmosClient = _cosmosDbContainer.CosmosClient;

var cosmosClientOptions = new CosmosClientOptions();
cosmosClientOptions.ConnectionMode = ConnectionMode.Gateway;
cosmosClientOptions.HttpClientFactory = () => httpClient;
var database = (await cosmosClient.CreateDatabaseIfNotExistsAsync("dbfake")).Database;
await database.CreateContainerIfNotExistsAsync("containerfake", "/id");
var container = database.GetContainer("containerfake");

var id = Guid.NewGuid().ToString();
var name = Guid.NewGuid().ToString();

using var cosmosClient = new CosmosClient(_cosmosDbContainer.GetConnectionString(), cosmosClientOptions);

// When
var accountProperties = await cosmosClient.ReadAccountAsync()
.ConfigureAwait(true);
var response = await container.CreateItemAsync(
Comment thread
NelsonBN marked this conversation as resolved.
Outdated
new FakeItem { id = id, Name = name },
new PartitionKey(id));

var itemResponse = await container.ReadItemAsync<FakeItem>(
id,
new PartitionKey(id));


// Then
Assert.Equal("localhost", accountProperties.Id);
Assert.Equal(id, itemResponse.Resource.id);
Assert.Equal(name, itemResponse.Resource.Name);
}


private class FakeItem
{
public string id { get; set; }
public string Name { get; set; }
}
}
}