Skip to content

Auto-start Cosmos emulator via Testcontainers#37999

Merged
AndriySvyryd merged 16 commits intomainfrom
copilot/automate-cosmos-emulator-startup
Apr 1, 2026
Merged

Auto-start Cosmos emulator via Testcontainers#37999
AndriySvyryd merged 16 commits intomainfrom
copilot/automate-cosmos-emulator-startup

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 25, 2026

Follow up to #37110

Replace explicit Docker scripts for the Cosmos emulator with automatic Testcontainers.CosmosDb lifecycle management, matching the pattern from #37809 for SQL Server. Also auto-detect the Linux emulator instead of requiring Test__Cosmos__EmulatorType=linux.

TestEnvironment connection initialization

3-path logic in TestEnvironment.InitializeAsync() (called once at assembly start via an xunit assembly fixture):

  1. Configured endpointTest__Cosmos__DefaultConnection env var or config file → use directly
  2. Localhost probe — probe https://localhost:8081 for an already-running emulator (e.g. Windows emulator or manually-started Docker container) → use if reachable
  3. Testcontainer — start CosmosDbContainer with vnext-preview image; dispose at assembly end via the fixture

The localhost probe enables a convenient developer workflow on Windows where the emulator can be running without needing to set an environment variable. When the testcontainer fails to start, the exception is wrapped with a helpful message explaining that either the Cosmos DB emulator should be running on localhost:8081, Docker must be installed and running, or the Test__Cosmos__DefaultConnection environment variable should be set to connect to an existing emulator or Cosmos DB instance.

DefaultConnection has a sensible default initial value (from config or https://localhost:8081) so it can be read safely from constructors before initialization. InitializeAsync() is called explicitly from CosmosTestStore.InitializeAsync() rather than implicitly from property getters, to avoid accidentally starting an emulator from unit tests. After initialization, CosmosTestStore updates its ConnectionUri and ConnectionString to reflect any changes (e.g., testcontainer startup).

Assembly fixture for container lifecycle

The testcontainer lifecycle is managed via an xunit assembly fixture (CosmosEmulatorFixture) using a custom CosmosTestFrameworkCosmosTestFrameworkExecutorCosmosTestAssemblyRunner chain:

  • CosmosEmulatorFixture.InitializeAsync() calls TestEnvironment.InitializeAsync() once at assembly start, before any test classes are constructed
  • CosmosEmulatorFixture.DisposeAsync() calls TestEnvironment.DisposeAsync() at assembly end, which stops and disposes the testcontainer if one was started
  • This replaces the previous ProcessExit event handler approach, ensuring proper cleanup through xunit's lifecycle

Linux emulator auto-detection

IsLinuxEmulator is now true when:

  • Testcontainer is running (always Linux image), or
  • OS is not Windows (existing heuristic), or
  • EmulatorType config explicitly set to "linux" (backward compat)

No env var required to opt into the Linux emulator — it is detected automatically.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits March 25, 2026 02:31
- Add Testcontainers.CosmosDb package reference
- Rewrite TestEnvironment.cs with lazy connection init that auto-starts
  a testcontainer when no emulator is configured or reachable
- Use testcontainer's HttpMessageHandler for URI rewriting
- Auto-detect Linux emulator (always true for testcontainers)
- Set cosmosConfig.json DefaultConnection to null for auto-detection
- Simplify helix.proj (remove manual Docker pre/post commands)
- Remove EmulatorType env var from copilot-setup-steps.yml
- Update SKILL.md with new testcontainer approach

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/655b1ac0-f385-43cf-9276-b3c6b2501432
Copy link
Copy Markdown
Member

@AndriySvyryd AndriySvyryd left a comment

Choose a reason for hiding this comment

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

@copilot Remove the run-cosmos-container scripts

Comment thread test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestEnvironment.cs Outdated
Comment thread test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestEnvironment.cs Outdated
Comment thread .github/workflows/copilot-setup-steps.yml
Comment thread eng/helix.proj
Comment thread eng/helix.proj
Comment thread test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestEnvironment.cs Outdated
Comment thread test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestEnvironment.cs Outdated
…re helix/copilot env vars, delete scripts

- Make TestEnvironment initialization fully async (InitializeAsync)
- Set DefaultConnection and HttpMessageHandler values during async init
- If SkipConnectionCheck=true, let testcontainer failures throw
- Create HttpClient instance outside the lambda in ApplyConfiguration
- Inline IsTestContainer (removed property)
- Restore copilot-setup-steps.yml env vars (EmulatorType, DefaultConnection, SkipConnectionCheck)
- Restore helix.proj Windows.11 block and SkipConnectionCheck for Ubuntu
- Delete eng/testing/run-cosmos-container.{sh,ps1}
- Update SKILL.md

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/7f2ba766-d1b7-484b-899c-4b6d320a97e5
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 25, 2026

@copilot Remove the run-cosmos-container scripts

Done in 6df36b8. Deleted both eng/testing/run-cosmos-container.sh and eng/testing/run-cosmos-container.ps1.

Copy link
Copy Markdown

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 EF Core Cosmos functional test infrastructure to automatically provision the Azure Cosmos DB emulator via Testcontainers.CosmosDb, replacing explicit Docker scripts and simplifying Linux emulator detection for CI and local runs.

Changes:

  • Add async Cosmos connection initialization with a configured-endpoint → localhost probe → testcontainer fallback sequence.
  • Switch Cosmos test HTTP handling to optionally use the testcontainer-provided HttpMessageHandler.
  • Remove Helix/Docker Cosmos emulator scripts and update CI/setup configuration and internal skill docs accordingly.

Reviewed changes

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

Show a summary per file
File Description
test/EFCore.Cosmos.FunctionalTests/cosmosConfig.json Sets DefaultConnection to null to enable auto-detection rather than forcing localhost.
test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestEnvironment.cs Implements async initialization, testcontainer startup, and Linux emulator auto-detection.
test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosTestStore.cs Ensures TestEnvironment.InitializeAsync() runs before connection availability checks.
test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosDbContextOptionsBuilderExtensions.cs Uses testcontainer handler when available; adjusts HttpClient creation/factory usage.
test/EFCore.Cosmos.FunctionalTests/EFCore.Cosmos.FunctionalTests.csproj Adds Testcontainers.CosmosDb dependency for Cosmos functional tests.
test/Directory.Packages.props Adds centralized package version for Testcontainers.CosmosDb.
eng/testing/run-cosmos-container.sh Removes Linux Docker script (superseded by testcontainers).
eng/testing/run-cosmos-container.ps1 Removes Windows Docker script (superseded by testcontainers).
eng/helix.proj Removes Ubuntu Cosmos Docker pre/post commands; relies on testcontainer auto-start.
.github/workflows/copilot-setup-steps.yml Pins Cosmos env vars to use the workflow’s service container and avoid starting a second emulator.
.agents/skills/cosmos-provider/SKILL.md Updates Cosmos test/emulator documentation to match the new testcontainer-based flow.

Comment thread test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestEnvironment.cs Outdated
Comment thread .agents/skills/cosmos-provider/SKILL.md Outdated
Comment thread test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestEnvironment.cs Outdated
Comment thread .agents/skills/cosmos-provider/SKILL.md Outdated
Comment thread .github/workflows/copilot-setup-steps.yml
…:false, add DefaultConnection initial value

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/2469bf2b-2857-4f34-89ee-e1c963e35d9d
Comment thread test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestEnvironment.cs Outdated
Comment thread .agents/skills/cosmos-provider/SKILL.md Outdated
…ILL.md suggestion

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/655b5153-de78-4ee4-988b-30f981564c60
@AndriySvyryd AndriySvyryd marked this pull request as ready for review March 25, 2026 20:45
@AndriySvyryd AndriySvyryd requested a review from a team as a code owner March 25, 2026 20:45
Copilot AI review requested due to automatic review settings March 25, 2026 20:45
Copilot AI requested a review from AndriySvyryd March 25, 2026 20:45
@AndriySvyryd AndriySvyryd assigned roji and unassigned AndriySvyryd and Copilot Mar 25, 2026
…remove localhost probing and failure fallback

Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/ab54e2d2-c2e8-4385-8da4-f514a5ab5f11

Co-authored-by: roji <1862641+roji@users.noreply.github.com>
Copilot finished work on behalf of roji March 28, 2026 07:46

_container = container;

AppDomain.CurrentDomain.ProcessExit += (_, _) =>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We'd ideally use an xunit assembly fixture to start and stop the container.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot use an xunit assembly fixture to start and stop the container.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 8ea3913. Implemented a custom xunit test framework (CosmosTestFrameworkCosmosTestFrameworkExecutorCosmosTestAssemblyRunner) that manages a CosmosEmulatorFixture as an assembly-wide fixture. The fixture calls TestEnvironment.InitializeAsync() before any tests run and TestEnvironment.DisposeAsync() after all tests complete. Removed the ProcessExit handler from TestEnvironment.

The Xunit.Extensions.AssemblyFixture NuGet package wasn't available in the configured feeds, so I implemented a minimal version inline using XunitTestFramework/XunitTestAssemblyRunner hooks.

Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/a26908c4-620d-4aab-becc-397ea330aed7

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot AI and others added 2 commits April 1, 2026 00:52
@AndriySvyryd
Copy link
Copy Markdown
Member

@copilot Revert changes from 8ea3913 and 3a44583

Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/cf8f0f07-50d1-47f8-b14b-4aa7f4231898

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 1, 2026

@copilot Revert changes from 8ea3913 and 3a44583effd3f8d8c39391...

Done in 91b538a. Reverted the xunit assembly fixture changes from 8ea3913 and 3a44583 — deleted CosmosEmulatorFixture.cs and CosmosTestFramework.cs, restored TestAssemblyCondition.cs and TestEnvironment.cs to their pre-assembly-fixture state (with ProcessExit handler for container disposal).

@AndriySvyryd AndriySvyryd merged commit 23054e8 into main Apr 1, 2026
16 checks passed
@AndriySvyryd AndriySvyryd deleted the copilot/automate-cosmos-emulator-startup branch April 1, 2026 16:36
@roji roji linked an issue Apr 20, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use testcontainer for testing Cosmos DB

4 participants