Skip to content

Make SQLite fallback reliable when Docker is unavailable - #1073

Open
MartinHock wants to merge 5 commits into
ardalis:mainfrom
MartinHock:issue/1028-reliable-sqlite-fallback
Open

Make SQLite fallback reliable when Docker is unavailable#1073
MartinHock wants to merge 5 commits into
ardalis:mainfrom
MartinHock:issue/1028-reliable-sqlite-fallback

Conversation

@MartinHock

@MartinHock MartinHock commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Make the functional test database provider explicitly selectable.
  • Keep SQL Server through Testcontainers as the preferred provider.
  • Fall back to SQLite only when Docker is unavailable.
  • Use an isolated temporary SQLite database for each test factory.
  • Clean up temporary SQLite database files after the test run.
  • Add tests that verify the SQLite provider and a functional endpoint using SQLite.

Behavior

When Docker is available:

  • SQL Server Testcontainers are used.
  • All functional tests run with SQL Server.
  • The Docker-specific test runs normally.

When Docker is unavailable:

  • The functional test factory falls back to SQLite.
  • The Docker-specific test is skipped.
  • The remaining functional tests continue to pass.

Only DockerUnavailableException triggers the fallback or skipped test. Other container or SQL Server startup errors remain visible as test failures.

Verification

With Docker running:

Total tests: 6
Passed: 6
Failed: 0
Skipped: 0


## Build note

The current upstream branch reports NU1903 for the vulnerable transitive
SQLite dependency and treats all warnings as errors.

This PR keeps NU1903 visible but excludes it from `TreatWarningsAsErrors`
so the functional-test changes can be built and verified.

The actual dependency update is handled separately in #1067.
@MartinHock

Copy link
Copy Markdown
Contributor Author

Hi maintainers,

Just a friendly follow-up after about two weeks.

I have addressed the review comments on my pull requests, and the current GitHub Actions workflows complete successfully on Ubuntu, Windows, and macOS.

However, my pull requests are still blocked because the repository requires a status check named build, which is no longer reported by the current workflow configuration.

As far as I can tell, this is not specific to my pull requests. It appears to affect other open pull requests as well.

I traced the required status check back to the former .github/workflows/dotnetcore.yml workflow, which contained the following job:
jobs:
build:

The current cross-platform workflow reports the individual matrix jobs successfully, but no longer reports a check named exactly build. As a result, GitHub continues waiting for a required status check that can no longer be produced.
Would someone with repository administrator permissions please review the branch protection rules and either:

  • update the required status checks to match the current workflow, or
    • add an appropriate aggregate build check if that is the preferred approach?
      I believe resolving this would unblock not only my pull requests but potentially other contributors’ pull requests as well.
      Thank you very much!
@MartinHock
MartinHock force-pushed the issue/1028-reliable-sqlite-fallback branch from 9917dce to a4bf844 Compare August 17, 2026 18:44
Copilot AI lite review requested due to automatic review settings August 17, 2026 18:44

Copilot AI left a comment

Copy link
Copy Markdown

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 aims to make functional tests resilient when Docker is unavailable by introducing an explicit test database provider selection mechanism that prefers SQL Server via Testcontainers and falls back to SQLite only on DockerUnavailableException. It also includes broader repo/tooling updates (test runner/reporting, analyzers, package updates, and configuration tidy-ups) that support running tests more consistently across environments.

Changes:

  • Add selectable functional-test DB provider (Auto/SqlServer/Sqlite) and implement SQL Server→SQLite fallback when Docker is unavailable.
  • Use isolated per-factory temporary SQLite databases and add functional tests validating SQLite provider + endpoint behavior.
  • Update packages/tooling/config (central package versions, analyzers, test reporting, dependabot, editorconfig/runsettings, and some code cleanups).

Reviewed changes

Copilot reviewed 53 out of 54 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tests/Clean.Architecture.UnitTests/NoOpMediator.cs Adjusts stream creation behavior in the unit-test mediator stub.
tests/Clean.Architecture.IntegrationTests/Data/EfRepositoryUpdate.cs Updates test fixture usage for DbContext access.
tests/Clean.Architecture.IntegrationTests/Data/BaseEfRepoTestFixture.cs Adds disposal + encapsulates DbContext behind a protected property.
tests/Clean.Architecture.IntegrationTests/Clean.Architecture.IntegrationTests.csproj Adds/updates test dependencies.
tests/Clean.Architecture.FunctionalTests/TestDatabaseProvider.cs Introduces provider selection enum for functional tests.
tests/Clean.Architecture.FunctionalTests/SqliteFallbackTests.cs Adds tests verifying SQLite selection and an endpoint works under SQLite.
tests/Clean.Architecture.FunctionalTests/CustomWebApplicationFactory.cs Implements SQL Server Testcontainers startup with Docker-unavailable SQLite fallback and service reconfiguration.
tests/Clean.Architecture.FunctionalTests/Clean.Architecture.FunctionalTests.csproj Adds/updates dependencies required for containerized functional tests + Docker probing.
tests/Clean.Architecture.FunctionalTests/ApiEndpoints/ContributorList.cs Updates SeedData constant name usage in functional endpoint tests.
tests/Clean.Architecture.AspireTests/Clean.Architecture.AspireTests.csproj Aligns test target framework with repository framework updates.
tests/.runsettings Enables parallel test execution configuration.
tests/.editorconfig Adds test-scope editorconfig conventions.
src/Clean.Architecture.Web/Contributors/Update.UpdateContributorValidator.cs Updates constants naming + removes unused using.
src/Clean.Architecture.Web/Contributors/Update.UpdateContributorRequest.cs Uses invariant culture for route building.
src/Clean.Architecture.Web/Contributors/Update.cs Removes unused using after use-case namespace changes.
src/Clean.Architecture.Web/Contributors/List.cs Uses renamed paging constants and passes cancellation token consistently.
src/Clean.Architecture.Web/Contributors/GetById.GetContributorByIdRequest.cs Uses invariant culture for route building.
src/Clean.Architecture.Web/Contributors/GetById.cs Updates to renamed use-case namespace.
src/Clean.Architecture.Web/Contributors/Delete.DeleteContributorRequest.cs Uses invariant culture for route building.
src/Clean.Architecture.Web/Contributors/Create.cs Passes cancellation token and removes redundant = null initializer.
src/Clean.Architecture.Web/Configurations/MiddlewareConfig.cs Formatting + log template consistency updates.
src/Clean.Architecture.Web/Configurations/LoggerConfigs.cs Uses invariant culture for console sink formatting.
src/Clean.Architecture.UseCases/Contributors/Update/UpdateContributorHandler.cs Cancellation token naming consistency + pass-through updates.
src/Clean.Architecture.UseCases/Contributors/List/ListContributorsQuery.cs Uses renamed paging constants.
src/Clean.Architecture.UseCases/Contributors/List/ListContributorsHandler.cs Uses renamed paging constants.
src/Clean.Architecture.UseCases/Contributors/GetContributor/GetContributorQuery.cs Moves query to a new namespace to clarify intent.
src/Clean.Architecture.UseCases/Contributors/Get/GetContributorHandler.cs Adjusts handler dependency naming and use-case namespace wiring.
src/Clean.Architecture.UseCases/Constants.cs Converts constants container to static and renames constants to PascalCase.
src/Clean.Architecture.ServiceDefaults/Extensions.cs Minor code-quality updates (warning pragmas, path comparisons).
src/Clean.Architecture.Infrastructure/Email/MimeKitEmailSender.cs Renames parameters and adjusts logging; minor formatting updates.
src/Clean.Architecture.Infrastructure/Email/FakeEmailSender.cs Keeps interface parity with renamed email parameters and adjusts logging.
src/Clean.Architecture.Infrastructure/Data/SeedData.cs Renames constants to PascalCase.
src/Clean.Architecture.Infrastructure/Data/EventDispatcherInterceptor.cs Minor change to domain-event presence check.
src/Clean.Architecture.Infrastructure/Data/Config/VogenEfCoreConverters.cs Seals EF Core converter partial type.
src/Clean.Architecture.Infrastructure/Data/Config/DataSchemaConstants.cs Renames constant to PascalCase.
src/Clean.Architecture.Infrastructure/Clean.Architecture.Infrastructure.csproj Adds explicit SQLitePCLRaw bundle dependency (security/vuln-related).
src/Clean.Architecture.Core/Services/DeleteContributorService.cs Improves documentation + adopts precompiled logging delegate pattern.
src/Clean.Architecture.Core/Interfaces/IEmailSender.cs Renames parameters for clarity (recipient/sender).
src/Clean.Architecture.Core/ContributorAggregate/Handlers/ContributorNameUpdatedEmailNotificationHandler.cs Log template parameter casing consistency.
src/Clean.Architecture.Core/ContributorAggregate/Handlers/ContributorDeletedHandler.cs Log template parameter casing consistency.
sample/tests/NimblePros.SampleToDo.FunctionalTests/NimblePros.SampleToDo.FunctionalTests.csproj Updates dependencies to match container/test changes.
sample/src/NimblePros.SampleToDo.Infrastructure/NimblePros.SampleToDo.Infrastructure.csproj Adds explicit SQLitePCLRaw dependency in sample.
sample/src/NimblePros.SampleToDo.AspireHost/NimblePros.SampleToDo.AspireHost.csproj Adds MessagePack and minor XML/encoding adjustments.
sample/Directory.Packages.props Central package updates for sample (incl. new dependencies).
MinimalClean/src/MinimalClean.Architecture.AspireHost/MinimalClean.Architecture.AspireHost.csproj Adds MessagePack reference.
MinimalClean/Directory.Packages.props Expands central package list for MinimalClean.
global.json Updates SDK/test runner configuration.
Directory.Packages.props Central package version updates + adds several new package versions.
Directory.Build.props Enables analyzers + modifies warnings-as-errors behavior and target framework.
Clean.Architecture.slnx Includes additional solution items (.gitignore, editorconfigs).
.gitignore Adds ignores for sonar workspace, local state.
.github/workflows/cross-platform-build-test.yml Updates dotnet test invocation + artifact upload behavior.
.github/dependabot.yml Adds grouped, labeled Dependabot configuration with schedule/timezone.
.editorconfig Adds analyzer severity overrides and minor formatting updates.

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

Comment thread tests/Clean.Architecture.UnitTests/NoOpMediator.cs Outdated
Comment on lines 76 to 80
public override async ValueTask DisposeAsync()
{
// Clean up environment variable
Environment.SetEnvironmentVariable("USE_SQL_SERVER", null);
if (_dbContainer != null)
{
Comment thread Directory.Build.props
Comment on lines 7 to 9
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
<TargetFramework>net10.0</TargetFramework>
Comment on lines 26 to 27
await client.DisconnectAsync(true,
new CancellationToken(canceled: true));
Comment on lines +10 to +16
public class GetContributorHandler(IReadRepository<Contributor> repository)
: IQueryHandler<GetContributorQuery, Result<ContributorDto>>
{
public async ValueTask<Result<ContributorDto>> Handle(GetContributorQuery request, CancellationToken cancellationToken)
{
var spec = new ContributorByIdSpec(request.ContributorId);
var entity = await _repository.FirstOrDefaultAsync(spec, cancellationToken);
var entity = await repository.FirstOrDefaultAsync(spec, cancellationToken);
Comment thread .editorconfig Outdated
Comment on lines +150 to +152
// CA1848: Use 'LoggerMessage.Define' instead of 'LoggerMessage.Define<T>'
// DO not force Logger Massages Delegates all everywhere
dotnet_diagnostic.CA1848.severity= none
Comment on lines +63 to +67
catch (DockerUnavailableException) when (
_requestedDatabaseProvider == TestDatabaseProvider.Auto)
{
await DisposeContainerAfterFailedStartAsync(container);
ActiveDatabaseProvider = TestDatabaseProvider.Sqlite;
@MartinHock
MartinHock force-pushed the issue/1028-reliable-sqlite-fallback branch from f864ae6 to 2923d3b Compare August 17, 2026 20:01
MartinHock added a commit to MartinHock/CleanArchitecture that referenced this pull request Aug 17, 2026
@MartinHock

Copy link
Copy Markdown
Contributor Author

@copilot Fix the code for all comments in this review thread.

When a review comment includes a suggested change, apply the suggestion exactly.

Do not make changes beyond what is described in the linked review thread.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants