Skip to content

feat(CosmosDb): Update base image from latest to vnext-preview#1324

Merged
HofmeisterAn merged 20 commits intotestcontainers:developfrom
NelsonBN:feature/update-cosmosdb-image-version
Mar 7, 2026
Merged

feat(CosmosDb): Update base image from latest to vnext-preview#1324
HofmeisterAn merged 20 commits intotestcontainers:developfrom
NelsonBN:feature/update-cosmosdb-image-version

Conversation

@NelsonBN
Copy link
Contributor

@NelsonBN NelsonBN commented Dec 31, 2024

What does this PR do?

This PR updates the CosmosDb image to the new version Microsoft is working on

Linux-based emulator (preview)
GitHub Repository

Why is it important?

This new image significantly improves the container startup process, eliminates certificate-related workarounds, and integrates seamlessly with CI/CD pipelines like GitHub Actions. For reference, you can check some of my tests here and GitActions here.

Related issues

#1306

Details

Explorer UI Disabled

The explorer UI was disabled since the container's purpose is to test integration with the Cosmos DB API.

return base.Init()
    .WithImage(CosmosDbImage)
    .WithEnvironment("ENABLE_EXPLORER", "false");

Internal Routing Configuration

For internal routing to work as expected, the API port and mapping port need to be configured with the same value. References.

.WithEnvironment("PORT", CosmosDbPort.ToString())
.WithPortBinding(CosmosDbPort, CosmosDbPort);

CosmosClient Configuration

The CosmosClient must be configured to use Gateway mode. See the official guidance.

public CosmosClient CosmosClient => new(GetConnectionString(), new() { ConnectionMode = ConnectionMode.Gateway });

Summary by CodeRabbit

  • New Features
    • Updated Cosmos DB emulator to vnext-preview, exposed a health-check port (8080) and introduced a JSON-based readiness/health-check flow; local emulator endpoints now use HTTP for simpler local development.
  • Tests
    • Reworked and reactivated Linux tests, added coverage for database/container creation and item read/write verification.

@netlify
Copy link

netlify bot commented Dec 31, 2024

Deploy Preview for testcontainers-dotnet ready!

Name Link
🔨 Latest commit 5f3c18b
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-dotnet/deploys/69ac54a8d42013000877136e
😎 Deploy Preview https://deploy-preview-1324--testcontainers-dotnet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Collaborator

@HofmeisterAn HofmeisterAn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for creating the PR. Have you seen this discussion? I would like to wait until an official version is published. In addition, we do not use static ports. While GetAvailablePort() does not return a static port per se, it may fail for remote container runtimes (it does not resolve the mapped port from the container host).

For internal routing to work as expected, the API port and mapping port need to be configured with the same value. References.

According to the discussion, this is unnecessary, and it is why we used the DelegatingHandler in the past.

I think we can prepare a PR and merge it as soon as the official version is published, but I favor and would like to implement the proposed changes from the discussion.

@NelsonBN
Copy link
Contributor Author

Thanks for creating the PR. Have you seen this discussion? I would like to wait until an official version is published. In addition, we do not use static ports. While GetAvailablePort() does not return a static port per se, it may fail for remote container runtimes (it does not resolve the mapped port from the container host).

For internal routing to work as expected, the API port and mapping port need to be configured with the same value. References.

According to the discussion, this is unnecessary, and it is why we used the DelegatingHandler in the past.

I think we can prepare a PR and merge it as soon as the official version is published, but I favor and would like to implement the proposed changes from the discussion.

@HofmeisterAn Thanks for your comment. I hadn't come across that discussion. I only checked if there were any open issues. I ended up commenting there in the discussion as well.

Looking at the discussion, it seems that using the rewriting of the DelegatingHandler is still the best approach, as it also removes the need to know in advance the port where the container will be randomly opened. Even so, some workarounds, like bypassing the certificate, are no longer necessary.

Copy link
Contributor

@WojciechNagorski WojciechNagorski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm waiting for this PR because currently, it takes forever to start the image :)

@HofmeisterAn
Copy link
Collaborator

I'm waiting for this PR because currently, it takes forever to start the image :)

You can already use the vnext-preview. The discussion (#1306 (comment)) includes the necessary changes and information on how to override the default configuration. Additionally, you can fall back to the generic builder if needed.

@mm-srtr
Copy link

mm-srtr commented May 7, 2025

I'm waiting for this PR because currently, it takes forever to start the image :)

You can already use the vnext-preview. The discussion (#1306 (comment)) includes the necessary changes and information on how to override the default configuration. Additionally, you can fall back to the generic builder if needed.

The solution recommended on the discussion (#1306 (comment)) is 100% stable. Sometimes I got internal server error 500. Logs shows the Failed to determine the https port for redirect. message.

@HofmeisterAn HofmeisterAn added module An official Testcontainers module enhancement New feature or request labels Sep 21, 2025
@HofmeisterAn HofmeisterAn force-pushed the develop branch 3 times, most recently from 4900ecd to 8fa5f1b Compare October 3, 2025 20:17
@HofmeisterAn
Copy link
Collaborator

Does anyone know if vnext-preview has become official in the meantime?

Copilot AI review requested due to automatic review settings February 28, 2026 21:47
@coderabbitai
Copy link

coderabbitai bot commented Feb 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Switches emulator image to vnext-preview, exposes health port 8080 and probes /alive, changes container endpoints and URI rewriting from HTTPS to HTTP, adds a dedicated health-check HttpClient/handler with JSON-based readiness gating, and updates tests to create/read items against the emulator.

Changes

Cohort / File(s) Summary
Image & Health Configuration
src/Testcontainers.CosmosDb/CosmosDbBuilder.cs, tests/Testcontainers.CosmosDb.Tests/Dockerfile
Emulator image tag changed to vnext-preview; added public CosmosDbHealthCheckPort = 8080; bind health port and set ENABLE_EXPLORER=false; readiness target set to http://localhost/alive.
Container HTTP API & URI Rewriting
src/Testcontainers.CosmosDb/CosmosDbContainer.cs
AccountEndpoint and URI rewriter switched from HTTPS to HTTP; removed custom server certificate validation in base handler; added internal HttpMessageHealthCheckHandler and HttpClient HttpClientHealthCheck; retained existing handlers/clients.
Health-check & Wait Logic
src/Testcontainers.CosmosDb/CosmosDbBuilder.cs, src/Testcontainers.CosmosDb/CosmosDbContainer.cs
Replaced single-request readiness check with JSON-based polling of /alive; WaitUntil now uses the health-check HttpClient and verifies JSON checks (gateway and postgres == "healthy") before marking ready.
Tests
tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs
Refactored tests: renamed AccountPropertiesIdReturnsLocalhostRetrieveItemCreated; added CreateDatabaseAndContainerSuccessful; added FakeItem; tests now create/read items via CosmosClient against the emulator.
Project File Whitespace
src/Testcontainers.CosmosDb/Testcontainers.CosmosDb.csproj
Added trailing newline at EOF (non-functional whitespace change).

Sequence Diagram

sequenceDiagram
    participant Starter as Container Startup
    participant Builder as CosmosDbBuilder
    participant HealthClient as HttpClient (health)
    participant HealthAPI as /alive Endpoint
    participant Ready as Readiness Gate

    Starter->>Builder: Initialize (bind ports :8080, set ENABLE_EXPLORER=false)
    Builder->>HealthClient: create health-check HttpClient/handler
    loop Poll /alive until ready
        Builder->>HealthClient: GET http://localhost/alive
        HealthClient->>HealthAPI: request /alive
        HealthAPI-->>HealthClient: 200 + JSON { checks: { gateway: "...", postgres: "..." } }
        HealthClient-->>Builder: return JSON
        Builder->>Builder: parse checks (gateway & postgres == "healthy"?)
        alt both healthy
            Builder-->>Ready: mark container ready
        else not healthy
            Builder->>Builder: wait/retry/backoff
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested reviewers

  • HofmeisterAn

Poem

🐰 Hopping to vnext with a twitch and a hop,
I poke /alive to see if it's up.
HTTP paths now lead the way,
Health-checks hum until they're OK.
Tests nibble carrots — the emulator's up! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The description includes all mandatory sections (What and Why) with substantive content, links supporting resources, and implementation details. It directly references the related issue #1306 as recommended.
Title check ✅ Passed The title 'feat(CosmosDb): Update base image from latest to vnext-preview' accurately captures the main change—updating the CosmosDb container image to vnext-preview. It is specific, clear, and directly reflects the primary modification across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Cosmos DB emulator used by the CosmosDb module/tests to Microsoft’s new Linux-based emulator image (vnext-preview) and adjusts the container/test wiring accordingly.

Changes:

  • Pin Cosmos DB emulator image to mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview.
  • Update CosmosDb container wiring to use HTTP and a new /alive-based readiness check (plus disable Explorer UI).
  • Unskip/expand integration tests to validate database/container creation and item CRUD via Gateway mode.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
tests/Testcontainers.CosmosDb.Tests/Dockerfile Updates emulator image tag to vnext-preview.
tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs Enables and expands integration tests against the new emulator.
src/Testcontainers.CosmosDb/CosmosDbBuilder.cs Updates default image tag, adds health-check port binding and /alive wait logic, disables Explorer.
src/Testcontainers.CosmosDb/CosmosDbContainer.cs Switches endpoint/rewrites to HTTP and adds a dedicated health-check HttpClient.
src/Testcontainers.CosmosDb/Testcontainers.CosmosDb.csproj Formatting/newline-only change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/Testcontainers.CosmosDb/CosmosDbBuilder.cs (1)

8-8: ⚠️ Potential issue | 🟠 Major

Avoid setting a preview image as the default module image.

Line 8 hardcodes vnext-preview as the default. That makes the public default depend on a preview channel, which can shift behavior unexpectedly for downstream users and CI. Prefer a stable/official default, with preview as explicit opt-in.

Is `mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview` still a preview-only tag, and what is the currently recommended stable GA tag for the Linux Cosmos DB emulator?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs` at line 8, The constant
CosmosDbImage currently hardcodes the preview tag; change the public default so
it uses the stable/GA image (replace the value of CosmosDbImage with the
recommended GA tag) and provide a separate constant (e.g., CosmosDbPreviewImage)
or configuration flag to opt into
"mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview" for
preview testing; update any code that references CosmosDbImage to use the new
default and allow selecting the preview constant explicitly. Ensure the new
default value is verified against the current official GA tag before committing.
🧹 Nitpick comments (1)
src/Testcontainers.CosmosDb/CosmosDbBuilder.cs (1)

162-164: Avoid swallowing readiness errors silently.

The empty catch makes startup failures difficult to diagnose in CI. Consider at least debug-level logging of the exception message before returning false.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs` around lines 162 - 164, The
empty catch block in CosmosDbBuilder (the catch immediately before the method's
final "return false") swallows exceptions and hinders CI debugging; change it to
catch (Exception ex) and emit a debug-level log of ex.Message/exception (using
the class's existing logger field such as _logger/Logger/Log or add an ILogger
if none exists) before returning false so readiness errors are recorded.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Testcontainers.CosmosDb/CosmosDbContainer.cs`:
- Around line 29-30: The XML summary is outdated: update the documentation for
the method/property that returns the HTTP client (e.g.,
GetHttpClient/CreateHttpClient/HttpClient in CosmosDbContainer) to state that
the client routes over HTTP and does not configure or bypass certificate
validation (remove any claim that it "trusts the emulator certificate"); also
update any related remarks/tags to reflect current behavior and remove
references to certificate validation or TLS trusts.
- Around line 31-37: The properties HttpClient and HttpClientHealthCheck
currently create new UriRewriter and HttpClient on every access; instead add a
single field-level UriRewriter (e.g., _uriRewriter and _uriRewriterHealth)
inside CosmosDbContainer (or a static cached instance) and change the properties
to construct HttpClient via new HttpClient(_uriRewriter, disposeHandler: false)
and new HttpClient(_uriRewriterHealth, disposeHandler: false) (or expose an
explicit factory method GetHttpClient(Func<UriRewriter, HttpClient>) that
documents ownership), ensuring the UriRewriter instances are reused and not
disposed by CosmosClient; reference the existing symbols HttpClient,
HttpClientHealthCheck, UriRewriter, CosmosDbContainer, and
CosmosDbBuilder.CosmosDbPort/CosmosDbHealthCheckPort when making the change.

In `@tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs`:
- Around line 36-42: The test reads databaseProperties via an unfiltered query
which is non-deterministic; instead, fetch the created DB by name: after using
cosmosClient.CreateDatabaseIfNotExistsAsync("fakedb") and creating the
container, call cosmosClient.GetDatabase("fakedb").ReadAsync() (or the sync
equivalent) to obtain the DatabaseProperties and then Assert.Equal("fakedb",
databaseProperties.Id); replace usage of
GetDatabaseQueryIterator<DatabaseProperties>().ReadNextAsync().First() with this
direct ReadAsync call on cosmosClient.GetDatabase("fakedb") to make the
assertion deterministic.

---

Duplicate comments:
In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs`:
- Line 8: The constant CosmosDbImage currently hardcodes the preview tag; change
the public default so it uses the stable/GA image (replace the value of
CosmosDbImage with the recommended GA tag) and provide a separate constant
(e.g., CosmosDbPreviewImage) or configuration flag to opt into
"mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview" for
preview testing; update any code that references CosmosDbImage to use the new
default and allow selecting the preview constant explicitly. Ensure the new
default value is verified against the current official GA tag before committing.

---

Nitpick comments:
In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs`:
- Around line 162-164: The empty catch block in CosmosDbBuilder (the catch
immediately before the method's final "return false") swallows exceptions and
hinders CI debugging; change it to catch (Exception ex) and emit a debug-level
log of ex.Message/exception (using the class's existing logger field such as
_logger/Logger/Log or add an ILogger if none exists) before returning false so
readiness errors are recorded.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d66a9f1 and 16aa1d8.

📒 Files selected for processing (5)
  • src/Testcontainers.CosmosDb/CosmosDbBuilder.cs
  • src/Testcontainers.CosmosDb/CosmosDbContainer.cs
  • src/Testcontainers.CosmosDb/Testcontainers.CosmosDb.csproj
  • tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs
  • tests/Testcontainers.CosmosDb.Tests/Dockerfile

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Testcontainers.CosmosDb/CosmosDbBuilder.cs (1)

163-163: Consider narrowing the exception handling or adding a brief comment.

The empty catch block silently swallows all exceptions. While this is acceptable for wait strategies (where failures mean "not ready, retry"), catching Exception could hide unexpected issues during development.

💡 Optional: Add clarity with targeted exception handling
-            catch { }
+            catch (Exception)
+            {
+                // Any failure (network, timeout, JSON parsing) means the container is not ready yet.
+                // Return false to trigger a retry.
+            }

Alternatively, consider catching more specific exceptions like HttpRequestException and JsonException if you want to surface truly unexpected errors.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs` at line 163, The empty catch
in CosmosDbBuilder (inside the wait/retry probe block) currently swallows all
exceptions; change it to catch specific exceptions (e.g., HttpRequestException,
JsonException, TaskCanceledException) or rethrow unexpected ones, and add a
short comment explaining that transient probe failures are ignored; refer to the
catch in the CosmosDbBuilder class (the wait/ready probe TRY/CATCH) and update
it to either list those exception types or log/throw for non-transient errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs`:
- Line 113: The health-check currently calls
((CosmosDbContainer)container).HttpClientHealthCheck inside a using, which
forces creation and disposal of a new HttpClient each access
(HttpClientHealthCheck is a getter that new's one), defeating pooling and
risking socket exhaustion; fix by either changing
CosmosDbContainer.HttpClientHealthCheck to return a single reusable HttpClient
instance (cache a private readonly HttpClient and return it) or, if the
container already manages lifetime, remove the using and stop disposing it in
CosmosDbBuilder.cs so the same HttpClient is reused across health checks (ensure
you call the container’s Dispose appropriately elsewhere).

---

Nitpick comments:
In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs`:
- Line 163: The empty catch in CosmosDbBuilder (inside the wait/retry probe
block) currently swallows all exceptions; change it to catch specific exceptions
(e.g., HttpRequestException, JsonException, TaskCanceledException) or rethrow
unexpected ones, and add a short comment explaining that transient probe
failures are ignored; refer to the catch in the CosmosDbBuilder class (the
wait/ready probe TRY/CATCH) and update it to either list those exception types
or log/throw for non-transient errors.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16aa1d8 and e1cbdff.

📒 Files selected for processing (1)
  • src/Testcontainers.CosmosDb/CosmosDbBuilder.cs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs (1)

36-39: ⚠️ Potential issue | 🟡 Minor

Use deterministic database read for the assertion source.

Using First() from an unfiltered listing can be order-dependent. Read the created database directly.

✅ Proposed fix
-        var databaseProperties = (await cosmosClient.GetDatabaseQueryIterator<DatabaseProperties>().ReadNextAsync()).First();
+        var databaseProperties = (await database.ReadAsync()).Resource;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs` around lines 36
- 39, The test currently obtains the database for assertion by enumerating
databases via
cosmosClient.GetDatabaseQueryIterator<DatabaseProperties>().ReadNextAsync() and
calling First(), which is order-dependent; instead, use the deterministic API to
read the created database directly by calling cosmosClient.GetDatabase("fakedb")
and invoking ReadAsync/ReadDatabaseAsync (or the equivalent synchronous read) on
that Database/DatabaseProperties handle returned after
CreateDatabaseIfNotExistsAsync; update the assertion source to use the result of
CreateDatabaseIfNotExistsAsync or the direct read of
cosmosClient.GetDatabase("fakedb") rather than querying and calling First().
🧹 Nitpick comments (1)
src/Testcontainers.CosmosDb/CosmosDbBuilder.cs (1)

163-163: Avoid swallowing all exceptions in the wait loop.

A blanket catch makes startup failures opaque. Catch expected transient exceptions and let unexpected ones surface.

♻️ Proposed adjustment
-            catch { }
+            catch (HttpRequestException)
+            {
+                return false;
+            }
+            catch (System.Text.Json.JsonException)
+            {
+                return false;
+            }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs` at line 163, The empty catch
in the CosmosDbBuilder wait loop swallows all exceptions; update the catch to
only handle expected transient exceptions (e.g., HttpRequestException,
TimeoutException, TaskCanceledException, SocketException) by catching those
specific types (using an exception variable), log the error/retry attempt, and
continue the loop, but rethrow or let any other unexpected exceptions bubble up
so startup failures are visible; locate the silent catch inside the
CosmosDbBuilder wait/retry method (the loop that polls Cosmos DB readiness) and
replace the blanket catch with type-specific catches and logging/rehrow
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs`:
- Around line 36-39: The test currently obtains the database for assertion by
enumerating databases via
cosmosClient.GetDatabaseQueryIterator<DatabaseProperties>().ReadNextAsync() and
calling First(), which is order-dependent; instead, use the deterministic API to
read the created database directly by calling cosmosClient.GetDatabase("fakedb")
and invoking ReadAsync/ReadDatabaseAsync (or the equivalent synchronous read) on
that Database/DatabaseProperties handle returned after
CreateDatabaseIfNotExistsAsync; update the assertion source to use the result of
CreateDatabaseIfNotExistsAsync or the direct read of
cosmosClient.GetDatabase("fakedb") rather than querying and calling First().

---

Nitpick comments:
In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs`:
- Line 163: The empty catch in the CosmosDbBuilder wait loop swallows all
exceptions; update the catch to only handle expected transient exceptions (e.g.,
HttpRequestException, TimeoutException, TaskCanceledException, SocketException)
by catching those specific types (using an exception variable), log the
error/retry attempt, and continue the loop, but rethrow or let any other
unexpected exceptions bubble up so startup failures are visible; locate the
silent catch inside the CosmosDbBuilder wait/retry method (the loop that polls
Cosmos DB readiness) and replace the blanket catch with type-specific catches
and logging/rehrow behavior.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1cbdff and 85e55ce.

📒 Files selected for processing (3)
  • src/Testcontainers.CosmosDb/CosmosDbBuilder.cs
  • src/Testcontainers.CosmosDb/CosmosDbContainer.cs
  • tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs (1)

26-32: Consider extracting CosmosClient creation to a helper.

Both tests create CosmosClient with identical configuration. A shared helper method would reduce duplication.

♻️ Optional refactor
private CosmosClient CreateCosmosClient()
{
    return new CosmosClient(
        _cosmosDbContainer.GetConnectionString(),
        new CosmosClientOptions
        {
            ConnectionMode = ConnectionMode.Gateway,
            HttpClientFactory = () => _cosmosDbContainer.HttpClient
        });
}

Then use using var cosmosClient = CreateCosmosClient(); in each test.

Also applies to: 51-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs` around lines 26
- 32, Extract the duplicated CosmosClient construction into a helper method
(e.g., CreateCosmosClient) that returns a new CosmosClient configured with
_cosmosDbContainer.GetConnectionString() and a CosmosClientOptions {
ConnectionMode = ConnectionMode.Gateway, HttpClientFactory = () =>
_cosmosDbContainer.HttpClient }; then replace the inline constructions in both
tests with using var cosmosClient = CreateCosmosClient(); so both occurrences
reuse the same setup and avoid duplication.
src/Testcontainers.CosmosDb/CosmosDbBuilder.cs (1)

114-114: Minor style: Add space after if.

📝 Suggested fix
-            if(_httpClient is null)
+            if (_httpClient is null)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs` at line 114, The conditional
in CosmosDbBuilder uses "if(_httpClient is null)" without a space after "if";
update the conditional that checks the _httpClient field (in class
CosmosDbBuilder) to follow style guidelines by adding a space so it reads "if
(_httpClient is null)" wherever that check appears.
src/Testcontainers.CosmosDb/CosmosDbContainer.cs (1)

41-46: Internal health-check properties have the same instance-per-access pattern.

HttpMessageHealthCheckHandler and HttpClientHealthCheck also allocate new instances on each property access. Consider caching these as fields, especially since WaitUntil in CosmosDbBuilder.cs already mitigates this by storing the client in _httpClient after first access.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Testcontainers.CosmosDb/CosmosDbContainer.cs` around lines 41 - 46, The
two properties HttpMessageHealthCheckHandler and HttpClientHealthCheck create
new instances on every access; change them to cached fields (e.g., private
readonly or lazy-initialized fields like _httpMessageHealthCheckHandler and
_httpClientHealthCheck) and initialize them once (or lazily) so the same
UriRewriter and HttpClient instances are reused across accesses; update any
existing property getters (HttpMessageHealthCheckHandler, HttpClientHealthCheck)
to return those cached fields and ensure lifecycle/Dispose expectations are
handled consistently (noting CosmosDbBuilder.WaitUntil already caches an
_httpClient).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs`:
- Around line 105-176: WaitUntil currently implements IDisposable and disposes
the HttpClient it obtains from CosmosDbContainer.HttpClientHealthCheck, but
Dispose() is never called causing a leak; remove IDisposable and the Dispose()
method, stop disposing the HttpClient, and treat the HttpClient as a
non-owning/shared instance (either keep the existing _httpClient as a simple
reference set from ((CosmosDbContainer)container).HttpClientHealthCheck inside
UntilAsync or replace with a static/shared HttpClient instance); update
references to RequestUri, _httpClient, UntilAsync and ensure no code calls
Dispose() on HttpClient from WaitUntil.
- Line 8: The default image constant CosmosDbImage currently points to the
preview tag
"mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview"; change
this so the preview image is not the default by either (a) replacing
CosmosDbImage with a stable/GA image tag (e.g., a specific GA tag or "latest")
or (b) making the preview opt-in: keep a stable default constant (e.g.,
CosmosDbStableImage), and add a builder option/constructor parameter or
environment-flag (e.g., bool usePreviewImage or UsePreviewImage()) to the
CosmosDbBuilder that, when true, returns the preview tag (CosmosDbPreviewImage)
instead of the stable default; update any usages of CosmosDbImage to use the
chosen property or method.

---

Nitpick comments:
In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs`:
- Line 114: The conditional in CosmosDbBuilder uses "if(_httpClient is null)"
without a space after "if"; update the conditional that checks the _httpClient
field (in class CosmosDbBuilder) to follow style guidelines by adding a space so
it reads "if (_httpClient is null)" wherever that check appears.

In `@src/Testcontainers.CosmosDb/CosmosDbContainer.cs`:
- Around line 41-46: The two properties HttpMessageHealthCheckHandler and
HttpClientHealthCheck create new instances on every access; change them to
cached fields (e.g., private readonly or lazy-initialized fields like
_httpMessageHealthCheckHandler and _httpClientHealthCheck) and initialize them
once (or lazily) so the same UriRewriter and HttpClient instances are reused
across accesses; update any existing property getters
(HttpMessageHealthCheckHandler, HttpClientHealthCheck) to return those cached
fields and ensure lifecycle/Dispose expectations are handled consistently
(noting CosmosDbBuilder.WaitUntil already caches an _httpClient).

In `@tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs`:
- Around line 26-32: Extract the duplicated CosmosClient construction into a
helper method (e.g., CreateCosmosClient) that returns a new CosmosClient
configured with _cosmosDbContainer.GetConnectionString() and a
CosmosClientOptions { ConnectionMode = ConnectionMode.Gateway, HttpClientFactory
= () => _cosmosDbContainer.HttpClient }; then replace the inline constructions
in both tests with using var cosmosClient = CreateCosmosClient(); so both
occurrences reuse the same setup and avoid duplication.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85e55ce and a30b54a.

📒 Files selected for processing (3)
  • src/Testcontainers.CosmosDb/CosmosDbBuilder.cs
  • src/Testcontainers.CosmosDb/CosmosDbContainer.cs
  • tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs

@NelsonBN
Copy link
Contributor Author

NelsonBN commented Mar 1, 2026

Does anyone know if vnext-preview has become official in the meantime?

Currently, the vnext-preview version has not yet been incorporated into the latest tag. Doc: emulator-linux
However, the vnext-preview tag is continuously updated and maintained, as is the case with the latest release azure-cosmos-emulator:vnext-EN20260227. Whenever a new preview version is released, the vnext-preview tag is updated.

Previous versions are no longer supported, according to Microsoft documentation. emulator-release-notes

Another important point is that these newer versions already support more efficient health check mechanisms. I have updated the PR to support these new mechanisms.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/Testcontainers.CosmosDb/CosmosDbBuilder.cs (1)

162-162: Consider logging exceptions for debugging purposes.

The empty catch block is acceptable for wait strategies (returning false on failure is correct), but swallowing exceptions silently can make debugging difficult when the emulator fails to start.

💡 Optional: Add trace logging
-            catch { }
+            catch (Exception ex)
+            {
+                // Log at trace level for debugging without affecting normal operation
+                System.Diagnostics.Debug.WriteLine($"CosmosDB health check failed: {ex.Message}");
+            }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs` at line 162, The empty catch
in CosmosDbBuilder.cs swallows exceptions and makes debugging hard; update the
catch (around the wait strategy that currently returns false) to log the caught
Exception (include ex.Message and stack trace) instead of doing nothing—use the
existing logging mechanism if available (e.g., an ILogger instance or
Trace/Debug) and keep the current behavior of returning false after logging so
the wait strategy semantics remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/Testcontainers.CosmosDb/CosmosDbBuilder.cs`:
- Line 162: The empty catch in CosmosDbBuilder.cs swallows exceptions and makes
debugging hard; update the catch (around the wait strategy that currently
returns false) to log the caught Exception (include ex.Message and stack trace)
instead of doing nothing—use the existing logging mechanism if available (e.g.,
an ILogger instance or Trace/Debug) and keep the current behavior of returning
false after logging so the wait strategy semantics remain unchanged.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a30b54a and dd50e95.

📒 Files selected for processing (1)
  • src/Testcontainers.CosmosDb/CosmosDbBuilder.cs

@HofmeisterAn
Copy link
Collaborator

HofmeisterAn commented Mar 6, 2026

Unfortunately, Microsoft has not provided clear communication regarding their roadmap and plans. This PR has been open for a while, and the old latest version only works in certain cases. Since we expect developers to pin the image, I was wondering if we should proceed with the PR and publish the version that is compatible with vnext-preview, while dropping support for the old "official" version (breaking change). At least this way, developers can use it.

I can merge develop on the weekend.

@NelsonBN
Copy link
Contributor Author

NelsonBN commented Mar 6, 2026

Unfortunately, Microsoft has not provided clear communication regarding their roadmap and plans. This PR has been open for a while, and the old latest version only works in certain cases. Since we expect developers to pin the image, I was wondering if we should proceed with the PR and publish the version that is compatible with vnext-preview, while dropping support for the old "official" version (breaking change). At least this way, developers can use it.

I can merge develop on the weekend.

I agree that we should proceed with the vnext-preview version. Even though this image is still in preview, it's more useful than the old (latest) one. The current latest (old) version has several issues, especially with warmup. Because of that, the risk of breaking changes is probably low, since the warmup time in the current latest version makes it almost unusable.

Copy link
Collaborator

@HofmeisterAn HofmeisterAn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I double-checked the implementation in the other Testcontainers language implemenations and aligned the .NET implementation with them. They’re already using vnext-preview.

@HofmeisterAn HofmeisterAn changed the title feat: Update CosmosDb image to vnext-preview version feat(CosmosDb): Update base image from latest to vnext-preview Mar 7, 2026
@HofmeisterAn HofmeisterAn added the breaking change Causing compatibility issues label Mar 7, 2026
@HofmeisterAn HofmeisterAn merged commit 70ea93f into testcontainers:develop Mar 7, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Causing compatibility issues enhancement New feature or request module An official Testcontainers module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants