Skip to content

Share test containers per assembly via xUnit assembly fixtures - #10342

Merged
glen-84 merged 1 commit into
mainfrom
gai/share-test-containers-per-assembly
Sep 3, 2026
Merged

glen-84 merged 1 commit into
mainfrom
gai/share-test-containers-per-assembly

Conversation

@glen-84

@glen-84 glen-84 commented Sep 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Container-backed test projects declare their CookieCrumble resource as an xUnit [assembly: AssemblyFixture], so a run starts one container per assembly instead of one per test class: Data.Raven.Tests, the four Data.MongoDb.*.Tests projects, PersistedOperations.Redis.Tests, PersistedOperations.AzureBlobStorage.Tests, Subscriptions.Postgres.Tests, Subscriptions.Redis.Tests, Fusion.Subscriptions.NATS.Tests, and Fusion.Subscriptions.Redis.Tests. The two NATS-over-HTTP classes in Fusion.AspNetCore.Tests share one collection fixture instead of starting a container per test.
  • ContainerResource<T> gains a DisposeAsyncCore hook that runs before the container is disposed. RedisResource caches one multiplexer and MongoResource one client, both owned and disposed by the resource. NatsResource.CreateStreamAsync returns a uniquely named JetStream stream that deletes itself on dispose, replacing the per-test stream helpers in three test projects.
  • RedisIntegrationTests scopes its PUBSUB CHANNELS probe to the subscription's own channel so the unsubscribe test holds on a server shared with the topic-prefix class.

Test plan

  • Full suite of every converted project passes: Raven 19, Mongo Projections 30 / Sorting 23 / Paging 39 / Filters 122, PersistedOperations Redis 19 / Azure Blob 12, Subscriptions Postgres 73 / Redis 19 (three consecutive runs), Fusion NATS 9 / Redis 7, Fusion.AspNetCore 546 with the 49 pre-existing skips, Fusion.Execution NATS gateway test 1.
  • Container count sampled during each run shows one container per assembly, down from three for Raven, up to thirteen for Mongo Filters, and eight per-test starts for Fusion.AspNetCore.
  • The NATS-over-HTTP tests on a shared server without stream cleanup fail six of eight with subjects overlap with an existing stream; with the self-deleting stream all eight pass.

Copilot AI lite review requested due to automatic review settings September 3, 2026 10:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The changes are internally consistent across the converted test assemblies and the new shared-resource disposal hooks cleanly manage cached clients without introducing behavioral issues in the updated tests.

Pull request overview

This PR reduces container churn in integration tests by moving container-backed resources to xUnit assembly fixtures (one container per test assembly) and by making shared container resources own and reuse their client connections safely across all tests in that assembly.

Changes:

  • Convert multiple test projects from per-class IClassFixture<T> usage to [assembly: AssemblyFixture(typeof(...))] for container-backed resources.
  • Add a DisposeAsyncCore hook to ContainerResource<T> and update Redis/Mongo/NATS resources to cache and dispose their client connections once per fixture.
  • Introduce NatsResource.CreateStreamAsync + NatsStream to create uniquely named, self-deleting JetStream streams and update NATS tests to use it; also scope the Redis PUBSUB CHANNELS probe to the subscription’s own channel.
File summaries
File Description
src/HotChocolate/Raven/test/Data.Raven.Tests/FluentApiTests.cs Remove per-class fixture interface in favor of assembly fixture injection.
src/HotChocolate/Raven/test/Data.Raven.Tests/DataExtensionsTests.cs Remove per-class fixture interface in favor of assembly fixture injection.
src/HotChocolate/Raven/test/Data.Raven.Tests/Assembly.cs Register RavenDBResource as an assembly fixture.
src/HotChocolate/Raven/test/Data.Raven.Tests/AnnotationBasedTests.cs Remove per-class fixture interface; rely on injected resource.
src/HotChocolate/PersistedOperations/test/PersistedOperations.Redis.Tests/ServiceCollectionExtensionsTests.cs Stop using IClassFixture<RedisResource>; rely on assembly fixture injection.
src/HotChocolate/PersistedOperations/test/PersistedOperations.Redis.Tests/RequestExecutorBuilderTests.cs Stop using IClassFixture<RedisResource>; rely on assembly fixture injection.
src/HotChocolate/PersistedOperations/test/PersistedOperations.Redis.Tests/RedisOperationDocumentStorageTests.cs Stop using IClassFixture<RedisResource>; rely on assembly fixture injection.
src/HotChocolate/PersistedOperations/test/PersistedOperations.Redis.Tests/IntegrationTests.cs Stop using IClassFixture<RedisResource>; rely on assembly fixture injection.
src/HotChocolate/PersistedOperations/test/PersistedOperations.Redis.Tests/Assembly.cs Register RedisResource as an assembly fixture.
src/HotChocolate/PersistedOperations/test/PersistedOperations.AzureBlobStorage.Tests/ServiceCollectionExtensionsTests.cs Stop using IClassFixture<AzureStorageBlobResource>; rely on assembly fixture injection.
src/HotChocolate/PersistedOperations/test/PersistedOperations.AzureBlobStorage.Tests/RequestExecutorBuilderTests.cs Stop using IClassFixture<AzureStorageBlobResource>; rely on assembly fixture injection.
src/HotChocolate/PersistedOperations/test/PersistedOperations.AzureBlobStorage.Tests/IntegrationTests.cs Stop using IClassFixture<AzureStorageBlobResource>; rely on assembly fixture injection.
src/HotChocolate/PersistedOperations/test/PersistedOperations.AzureBlobStorage.Tests/AzureBlobStorageOperationDocumentStorageTests.cs Stop using IClassFixture<AzureStorageBlobResource>; rely on assembly fixture injection.
src/HotChocolate/PersistedOperations/test/PersistedOperations.AzureBlobStorage.Tests/Assembly.cs Register AzureStorageBlobResource as an assembly fixture.
src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbSortVisitorStringTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbSortVisitorObjectTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbSortVisitorEnumTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbSortVisitorComparableTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbSortVisitorBooleanTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbSortCollectionTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbFindFluentTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/MongoDbAggregateFluentTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Sorting.Tests/Assembly.cs Register MongoResource as an assembly fixture (sorting tests).
src/HotChocolate/MongoDb/test/Data.MongoDb.Projections.Tests/MongoDbProjectionVisitorScalarTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Projections.Tests/MongoDbProjectionVisitorPagingTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Projections.Tests/MongoDbProjectionVisitorIsProjectedTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Projections.Tests/MongoDbProjectionObjectTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Projections.Tests/Assembly.cs Register MongoResource as an assembly fixture (projections tests).
src/HotChocolate/MongoDb/test/Data.MongoDb.Paging.Tests/MongoDbOffsetPagingFindFluentTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Paging.Tests/MongoDbOffsetPagingAggregateTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Paging.Tests/MongoDbCursorPagingFindFluentTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Paging.Tests/MongoDbCursorPagingAggregateFluentTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Paging.Tests/Assembly.cs Register MongoResource as an assembly fixture (paging tests).
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFindFluentTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterVisitorTimeOnlyTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterVisitorStringTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterVisitorObjectTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterVisitorObjectIdTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterVisitorListTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterVisitorEnumTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterVisitorDateOnlyTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterVisitorComparableTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterVisitorBooleanTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbFilterCombinatorTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbCollectionTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/MongoDbAggregateFluentTests.cs Remove IClassFixture<MongoResource>; rely on assembly fixture injection.
src/HotChocolate/MongoDb/test/Data.MongoDb.Filters.Tests/Assembly.cs Register MongoResource as an assembly fixture (filters tests).
src/HotChocolate/Fusion/test/Fusion.Subscriptions.Redis.Tests/RedisSubscriptionTests.cs Remove IClassFixture<RedisFixture>; rely on assembly fixture injection.
src/HotChocolate/Fusion/test/Fusion.Subscriptions.Redis.Tests/RedisEventStreamBrokerTests.cs Remove IClassFixture<RedisFixture>; rely on assembly fixture injection.
src/HotChocolate/Fusion/test/Fusion.Subscriptions.Redis.Tests/Assembly.cs Register RedisFixture as an assembly fixture.
src/HotChocolate/Fusion/test/Fusion.Subscriptions.NATS.Tests/NatsSubscriptionTests.cs Remove IClassFixture<NatsResource>; rely on assembly fixture injection.
src/HotChocolate/Fusion/test/Fusion.Subscriptions.NATS.Tests/NatsEventStreamBrokerTests.cs Switch to NatsResource.CreateStreamAsync and remove per-test stream helper.
src/HotChocolate/Fusion/test/Fusion.Subscriptions.NATS.Tests/Assembly.cs Register NatsResource as an assembly fixture.
src/HotChocolate/Fusion/test/Fusion.Execution.Tests/Execution/Subscriptions/NatsEventStreamGatewayTests.cs Use NatsResource.CreateStreamAsync and remove per-test stream helper.
src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/NatsEventStreamOverHttpTests.cs Share NATS server via collection fixture and use self-deleting streams.
src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/NatsCollectionFixture.cs Add a collection fixture to share NatsResource across selected tests.
src/HotChocolate/Fusion/test/Fusion.AspNetCore.Tests/EventStreamEnrichmentErrorOverHttpTests.cs Share NATS server via collection fixture and use self-deleting streams.
src/HotChocolate/Core/test/Subscriptions.Redis.Tests/RedisTopicPrefixIntegrationTests.cs Remove IClassFixture<RedisResource>; rely on assembly fixture injection.
src/HotChocolate/Core/test/Subscriptions.Redis.Tests/RedisIntegrationTests.cs Scope PUBSUB CHANNELS probe to the subscription’s channel (MD5 topic hash).
src/HotChocolate/Core/test/Subscriptions.Redis.Tests/Assembly.cs Register RedisResource as an assembly fixture.
src/HotChocolate/Core/test/Subscriptions.Postgres.Tests/ResilientNpgsqlConnectionTests.cs Remove IClassFixture<PostgreSqlResource>; rely on assembly fixture injection.
src/HotChocolate/Core/test/Subscriptions.Postgres.Tests/PostgresPubSubIntegrationTests.cs Remove IClassFixture<PostgreSqlResource>; rely on assembly fixture injection.
src/HotChocolate/Core/test/Subscriptions.Postgres.Tests/PostgresChannelWriterTests.cs Remove IClassFixture<PostgreSqlResource>; rely on assembly fixture injection.
src/HotChocolate/Core/test/Subscriptions.Postgres.Tests/PostgresChannelTests.cs Remove IClassFixture<PostgreSqlResource>; rely on assembly fixture injection.
src/HotChocolate/Core/test/Subscriptions.Postgres.Tests/Assembly.cs Register PostgreSqlResource as an assembly fixture.
src/CookieCrumble/src/CookieCrumble.Resources/ContainerResource.cs Add DisposeAsyncCore hook invoked before container disposal.
src/CookieCrumble/src/CookieCrumble.Resources.Redis/RedisResource.cs Cache and dispose a single multiplexer per resource lifetime.
src/CookieCrumble/src/CookieCrumble.Resources.Nats/NatsStream.cs Add disposable wrapper that deletes a JetStream stream on dispose.
src/CookieCrumble/src/CookieCrumble.Resources.Nats/NatsResource.cs Add cached connection + CreateStreamAsync for unique, self-cleaning streams.
src/CookieCrumble/src/CookieCrumble.Resources.Nats/CookieCrumble.Resources.Nats.csproj Add NATS client package references required for stream management.
src/CookieCrumble/src/CookieCrumble.Resources.Mongo/MongoResource.cs Cache and dispose a single client per resource lifetime.
Review details
  • Files reviewed: 71/71 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Patch coverage

100.0% of changed lines covered (60/60)

File Covered Changed Patch %
…/src/CookieCrumble.Resources.Mongo/MongoResource.cs 12 12 100.0% 🟢
…/src/CookieCrumble.Resources.Nats/NatsResource.cs 22 22 100.0% 🟢
…/CookieCrumble/src/CookieCrumble.Resources.Nats/NatsStream.cs 7 7 100.0% 🟢
…/src/CookieCrumble.Resources.Redis/RedisResource.cs 11 11 100.0% 🟢
…/src/CookieCrumble.Resources/ContainerResource.cs 8 8 100.0% 🟢

Project coverage: 57.8% (287218/497237 lines)

@glen-84
glen-84 merged commit 40476f0 into main Sep 3, 2026
152 checks passed
@glen-84
glen-84 deleted the gai/share-test-containers-per-assembly branch September 3, 2026 11:03
This was referenced Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants