PouryaKit.Testing
0.1.0-preview.2
dotnet add package PouryaKit.Testing --version 0.1.0-preview.2
NuGet\Install-Package PouryaKit.Testing -Version 0.1.0-preview.2
<PackageReference Include="PouryaKit.Testing" Version="0.1.0-preview.2" />
<PackageVersion Include="PouryaKit.Testing" Version="0.1.0-preview.2" />
<PackageReference Include="PouryaKit.Testing" />
paket add PouryaKit.Testing --version 0.1.0-preview.2
#r "nuget: PouryaKit.Testing, 0.1.0-preview.2"
#:package PouryaKit.Testing@0.1.0-preview.2
#addin nuget:?package=PouryaKit.Testing&version=0.1.0-preview.2&prerelease
#tool nuget:?package=PouryaKit.Testing&version=0.1.0-preview.2&prerelease

PouryaKit.Testing
Test your application the way it runs. One HostFixture per test assembly builds the real Host with the same composition Program uses, starts PostgreSQL in a container, applies every Module's migrations and starts the application on it. Each test class derives from HostTest<TFixture>, which waits for the deliveries an earlier test caused and then empties every table, so no test sees another's data.
Install
dotnet add package PouryaKit.Testing --prerelease
When to use it
- You test a Feature against the hosted application, through its Module's Gateway or over HTTP.
- A test needs a particular Actor, tenant or correlation, or a fixed time.
- You wait for the deliveries an Operation caused and assert what they did, or read and replay a dead letter.
- You abandon a Host mid-delivery to test a crash.
It runs on xUnit v3 and Testcontainers, and hosts whatever your Program composes with PouryaKit.Modularity and PouryaKit.Messaging.Wolverine.EFCore.
Quick start
Derive one fixture for the assembly, over your Host's composition, as the templates generate it:
[assembly: AssemblyFixture(typeof(App))]
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
public sealed class App : HostFixture
{
protected override IHost CreateHost(string connectionString) =>
ComposeHost(Environments.Development, connectionString);
}
Send Operations through the Gateway, and assert Results and rows, as the Kit's tests do:
[Fact]
public async Task A_category_counts_a_new_product_in_the_same_commit_and_a_failed_count_leaves_no_product()
{
var catalog = Fixture.Gateway<CatalogModule>();
var lamps = Guid.CreateVersion7();
await catalog.SendAsync(
new CreateCategoryCommand(lamps, "Lamps"),
TestContext.Current.CancellationToken
);
var created = await catalog.SendAsync(
new CreateProductCommand(Guid.CreateVersion7(), lamps, "Desk lamp"),
TestContext.Current.CancellationToken
);
var refused = await catalog.SendAsync(
new CreateProductCommand(Guid.CreateVersion7(), Guid.CreateVersion7(), "Floor lamp"),
TestContext.Current.CancellationToken
);
Assert.True(created.IsSuccess);
Assert.Equal(CategoryErrors.NotFound, Assert.Single(refused.Errors));
Assert.Equal(
[
[lamps, 1],
],
await Fixture.RowsAsync("select id, product_count from catalog.categories")
);
Assert.Equal(
["Desk lamp"],
(await Fixture.RowsAsync("select name from catalog.products")).Select(row => row[0])
);
}
A Gateway call without a context runs as the test Actor with no tenant, and a tenant-scoped Module refuses it. The test above sends through an extension in the Kit's own tests that supplies a tenant. In your project, give a tenant-scoped Module a context that names one, and pass it to the Gateway's own methods:
var context = new OperationContext(GatewayTestExtensions.TestActor, tenant);
Assert.True(
(
await catalog.SendAsync(
new CreateCategoryCommand(category, "Lamps"),
context,
TestContext.Current.CancellationToken
)
).IsSuccess
);
What you get
- The real Host, composed as
Programcomposes it, on real PostgreSQL. - Every table emptied between tests.
- Deliveries awaited, and dead letters read and replayed.
- A fixed clock, and a chosen Actor and tenant for an Operation.
HostFixture runs PostgreSQL in a Testcontainers container, so the machine that runs the tests needs Docker. Tests that share a fixture run one at a time.
Learn more
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.TimeProvider.Testing (>= 10.11.0)
- PouryaKit.Messaging.Wolverine.EFCore (>= 0.1.0-preview.2)
- PouryaKit.Modularity (>= 0.1.0-preview.2)
- PouryaKit.Persistence.Postgres (>= 0.1.0-preview.2)
- Respawn (>= 7.0.0)
- Testcontainers.PostgreSql (>= 4.16.0)
- WolverineFx.RuntimeCompilation (>= 6.52.0)
- xunit.v3.extensibility.core (>= 4.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-preview.2 | 67 | 11/1/2026 |
| 0.1.0-preview.1 | 81 | 10/31/2026 |
| 0.1.0-preview.0.28 | 70 | 10/26/2026 |