๐Ÿ”Œ Integrations

April 6, 2026 ยท View on GitHub

NotoriousTest provides ready-to-use infrastructure packages for the most common external dependencies.

Summary


Available Packages

PackageDescription
NotoriousTest.WebASP.NET Core web application factory with automatic configuration injection
NotoriousTest.TestContainersGeneric base class for any Testcontainers-powered Docker container
NotoriousTest.DatabaseAbstract base classes for database infrastructures (Docker & external)
NotoriousTest.SqlServerSQL Server โ€” Docker container or external server
NotoriousTest.PostgreSqlPostgreSQL โ€” Docker container or external server
NotoriousTest.SqliteSQLite โ€” file-based database

๐ŸŒ Web โ€” NotoriousTest.Web

Provides infrastructure for testing ASP.NET Core applications. The web application is automatically configured with all configuration entries produced by other infrastructures.

Installation

dotnet add package NotoriousTest.Web

Defining a Web Application

Create a class inheriting from WebApplication<TEntryPoint>, where TEntryPoint is your application's Program class:

public class TestWebApplication : WebApplication<Program>
{
    // Override WebApplicationFactory methods if needed
    // e.g. ConfigureWebHost, CreateHost, etc.
}

Registering in an Environment

Use the AddWebApplication<T>() extension method from NotoriousTest.Web:

public class MyTestEnvironment : NotoriousTest.XUnit.Environment
{
    public override Assembly CurrentAssembly => Assembly.GetExecutingAssembly();

    public override async Task ConfigureEnvironment()
    {
        AddInfrastructure<MyDatabaseInfrastructure>(); // produces configuration
        this.AddWebApplication<TestWebApplication>();   // consumes it automatically
    }
}

๐Ÿ“Œ Key Points:

  • WebApplicationInfrastructure always initializes with Order = 999 โ€” after all other infrastructures.
  • It implements IConfigurationConsumer: all ConfigurationEntry objects produced by other infrastructures are injected into the app's IConfiguration at startup.
  • Nested objects are flattened to colon-separated appsettings keys: "ConnectionStrings:MyDb".

Using in Tests

HttpClient client = CurrentEnvironment.GetWebApplication().HttpClient;
HttpResponseMessage response = await client.GetAsync("api/health");
Assert.True(response.IsSuccessStatusCode);

๐Ÿณ Generic Docker Containers โ€” NotoriousTest.TestContainers

Provides a base class to integrate any Testcontainers container that is not a database.

Installation

dotnet add package NotoriousTest.TestContainers

Usage

Inherit from DockerContainerInfrastructure<TContainer, TOutputConfiguration>, where TContainer is any IContainer from the Testcontainers library:

public class RedisInfrastructure : DockerContainerInfrastructure<RedisContainer, RedisConfig>
{
    public RedisInfrastructure(EnvironmentId contextId, ITestLogger logger, IRegistry registry)
        : base(contextId, logger, registry)
    {
        Container = new RedisBuilder().Build();
    }

    public override async Task Initialize()
    {
        await base.Initialize(); // starts the container

        AddEntry("Redis:ConnectionString", new RedisConfig
        {
            ConnectionString = Container.GetConnectionString()
        });
    }

    public override Task Reset() => Task.CompletedTask;
}

๐Ÿ“Œ Key Points:

  • base.Initialize() starts the container and registers its metadata (container ID, name) for DoggyDog crash recovery.
  • base.Destroy() force-removes the container via the Docker client.
  • The [Cleaner] attribute is already set on the base class โ€” Docker containers are cleaned up automatically after a crash.
  • TESTCONTAINERS_RYUK_DISABLED is set to true by default to prevent conflicts with Ryuk.

๐Ÿ—„๏ธ SQL Server โ€” NotoriousTest.SqlServer

Provides two variants: a Docker variant (Testcontainers) and an external variant (existing SQL Server instance).

Both variants:

  • Create a unique database per test session (named {DbPrefix}_{EnvironmentId})
  • Reset the database between each test using Respawn
  • Drop the database at the end of the session
  • Expose the connection string as a ConfigurationEntry for automatic injection into the web app

Installation

dotnet add package NotoriousTest.SqlServer

Docker variant

SqlServerContainerInfrastructure spins up a SQL Server Docker container using Testcontainers.

Minimal setup โ€” just inherit, nothing else required:

public class MyDatabaseInfrastructure : SqlServerContainerInfrastructure
{
    public MyDatabaseInfrastructure(EnvironmentId contextId, ITestLogger logger, IRegistry registry)
        : base(contextId, logger, registry) { }
}

Override Initialize() to create your schema after the database is ready:

public class MyDatabaseInfrastructure : SqlServerContainerInfrastructure
{
    public MyDatabaseInfrastructure(EnvironmentId contextId, ITestLogger logger, IRegistry registry)
        : base(contextId, logger, registry) { }

    public override async Task Initialize()
    {
        await base.Initialize(); // starts container, creates database, registers connection string

        using var connection = GetDatabaseConnection();
        await connection.OpenAsync();

        using var command = connection.CreateCommand();
        command.CommandText = "CREATE TABLE Users (Id INT PRIMARY KEY, Name NVARCHAR(100))";
        await command.ExecuteNonQueryAsync();
    }
}

Customization:

public class MyDatabaseInfrastructure : SqlServerContainerInfrastructure
{
    // Override the appsettings key used to expose the connection string
    protected override string ConnectionStringKey => "ConnectionStrings:MyDb";

    // Override the database name prefix (default: "NotoriousDb")
    public override string DbPrefix => "MyApp";

    // Customize the Docker container
    protected override MsSqlBuilder ConfigureSqlContainer(MsSqlBuilder builder)
        => builder.WithPassword("MyStr0ng!Password");

    // Exclude migration tables from Respawn reset
    public override string[] TableToIgnore => ["__EFMigrationsHistory"];

    // Filter schemas for Respawn
    public string[] SchemasToInclude => ["dbo"];
}

External variant

SqlServerInfrastructure connects to an existing SQL Server instance. The connection string is loaded from testsettings.json via SettingsExtension.

testsettings.json (must be copied to output directory):

{
  "SqlServerInfrastructure": {
    "ConnectionString": "Server=localhost;User Id=sa;Password=...;TrustServerCertificate=True"
  }
}

Usage:

public class MyDatabaseInfrastructure : SqlServerInfrastructure
{
    public MyDatabaseInfrastructure(EnvironmentId contextId, ITestSettingsProvider settings,
                                    ITestLogger logger, IRegistry registry)
        : base(contextId, settings, logger, registry) { }
}

The settings section key defaults to the class name. Override SectionName in the inherited SettingsExtension to use a custom key.


Using in Tests

Both variants expose the same methods:

var infra = CurrentEnvironment.GetInfrastructure<MyDatabaseInfrastructure>();

// Get a DbConnection pointing to the test database
await using var connection = infra.GetDatabaseConnection();
await connection.OpenAsync();

// Or get the connection string directly
string connectionString = infra.GetDatabaseConnectionString();

๐Ÿ˜ PostgreSQL โ€” NotoriousTest.PostgreSql

Same structure as SQL Server, with a Docker variant and an external variant.

Installation

dotnet add package NotoriousTest.PostgreSql

Docker variant

PostgreContainerInfrastructure spins up a PostgreSQL Docker container using Testcontainers.

public class MyDatabaseInfrastructure : PostgreContainerInfrastructure
{
    public MyDatabaseInfrastructure(EnvironmentId contextId, ITestLogger logger, IRegistry registry)
        : base(contextId, logger, registry) { }

    public override async Task Initialize()
    {
        await base.Initialize(); // starts container, creates database, registers connection string

        using var connection = GetDatabaseConnection();
        await connection.OpenAsync();

        using var command = connection.CreateCommand();
        command.CommandText = "CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT)";
        await command.ExecuteNonQueryAsync();
    }
}

Customization:

public class MyDatabaseInfrastructure : PostgreContainerInfrastructure
{
    protected override string ConnectionStringKey => "ConnectionStrings:MyDb";
    public override string DbPrefix => "MyApp";

    protected override PostgreSqlBuilder ConfigureSqlContainer(PostgreSqlBuilder builder)
        => builder.WithPassword("mysecretpassword");

    public string[] SchemasToInclude => ["public"];
}

External variant

PostgreInfrastructure connects to an existing PostgreSQL server. The connection string is loaded from testsettings.json.

testsettings.json:

{
  "PostgreInfrastructure": {
    "ConnectionString": "Host=localhost;Port=5432;Username=postgres;Password=..."
  }
}

Usage:

public class MyDatabaseInfrastructure : PostgreInfrastructure
{
    public MyDatabaseInfrastructure(EnvironmentId contextId, ITestSettingsProvider settings,
                                    ITestLogger logger, IRegistry registry)
        : base(contextId, settings, logger, registry) { }
}

Using in Tests

var infra = CurrentEnvironment.GetInfrastructure<MyDatabaseInfrastructure>();

await using var connection = (NpgsqlConnection)infra.GetDatabaseConnection();
await connection.OpenAsync();

๐Ÿชถ SQLite โ€” NotoriousTest.Sqlite

SqliteInfrastructure creates a unique SQLite database file per test session, and deletes it at the end.

SQLite has no Docker variant โ€” it is file-based by nature.

Installation

dotnet add package NotoriousTest.Sqlite

Configuration

testsettings.json:

{
  "SqliteInfrastructure": {
    "ConnectionString": "Data Source=tests.db"
  }
}

The connection string Data Source is used as the base path. The infrastructure appends _{EnvironmentId} to the filename to ensure uniqueness per session (e.g. tests_abc123.db).

Usage

public class MyDatabaseInfrastructure : SqliteInfrastructure
{
    public MyDatabaseInfrastructure(EnvironmentId contextId, ITestSettingsProvider settings,
                                    ITestLogger logger, IRegistry registry)
        : base(contextId, settings, logger, registry) { }

    public override async Task Initialize()
    {
        await base.Initialize(); // creates the database file

        using var connection = GetDatabaseConnection();
        await connection.OpenAsync();

        using var command = connection.CreateCommand();
        command.CommandText = "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)";
        await command.ExecuteNonQueryAsync();
    }
}

Using in Tests

var infra = CurrentEnvironment.GetInfrastructure<MyDatabaseInfrastructure>();

await using var connection = infra.GetDatabaseConnection();
await connection.OpenAsync();

๐Ÿ“Œ Key Points:

  • The database file is automatically deleted on Destroy().
  • Reset between tests is handled by Respawn (table-level reset, not file deletion).
  • GetDatabaseConnectionString() and GetServerConnectionString() return the same value โ€” SQLite makes no distinction.

๐Ÿ’ก Need help or have feedback? Join the community discussions or open an issue on GitHub.