๐ Integrations
April 6, 2026 ยท View on GitHub
NotoriousTest provides ready-to-use infrastructure packages for the most common external dependencies.
Summary
- Web โ
NotoriousTest.Web - Generic Docker Containers โ
NotoriousTest.TestContainers - SQL Server โ
NotoriousTest.SqlServer - PostgreSQL โ
NotoriousTest.PostgreSql - SQLite โ
NotoriousTest.Sqlite
Available Packages
| Package | Description |
|---|---|
NotoriousTest.Web | ASP.NET Core web application factory with automatic configuration injection |
NotoriousTest.TestContainers | Generic base class for any Testcontainers-powered Docker container |
NotoriousTest.Database | Abstract base classes for database infrastructures (Docker & external) |
NotoriousTest.SqlServer | SQL Server โ Docker container or external server |
NotoriousTest.PostgreSql | PostgreSQL โ Docker container or external server |
NotoriousTest.Sqlite | SQLite โ 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:
WebApplicationInfrastructurealways initializes withOrder = 999โ after all other infrastructures.- It implements
IConfigurationConsumer: allConfigurationEntryobjects produced by other infrastructures are injected into the app'sIConfigurationat 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_DISABLEDis set totrueby 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
ConfigurationEntryfor 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
SectionNamein the inheritedSettingsExtensionto 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()andGetServerConnectionString()return the same value โ SQLite makes no distinction.
๐ก Need help or have feedback? Join the community discussions or open an issue on GitHub.