Stratara.Testing.Orleans
4.4.4
Prefix Reserved
dotnet add package Stratara.Testing.Orleans --version 4.4.4
NuGet\Install-Package Stratara.Testing.Orleans -Version 4.4.4
<PackageReference Include="Stratara.Testing.Orleans" Version="4.4.4" />
<PackageVersion Include="Stratara.Testing.Orleans" Version="4.4.4" />
<PackageReference Include="Stratara.Testing.Orleans" />
paket add Stratara.Testing.Orleans --version 4.4.4
#r "nuget: Stratara.Testing.Orleans, 4.4.4"
#:package Stratara.Testing.Orleans@4.4.4
#addin nuget:?package=Stratara.Testing.Orleans&version=4.4.4
#tool nuget:?package=Stratara.Testing.Orleans&version=4.4.4
Stratara.Testing.Orleans
Derived. The behaviour described here is specified under
openspec/specs/. Those specifications are the source; this page explains and illustrates them.
Run the Orleans execution model in a test's own process. ExecutionModelTestHost starts one
silo clustered with itself, with reminders and the grain directory in memory, and the framework's
real write stack, portable commit-order reader, checkpoint store and intent store on an in-memory
SQLite database. Every period the model keeps as a reminder or a poll is shortened to seconds, so a
projection applies and a timer fires within a test. No cluster, no broker, no database server, no
Docker.
Builds on Stratara.Testing.EntityFrameworkCore.
Why run the real grains?
Because the registration is what a test should prove. Your handlers, projections, sagas, processes
and timer ports are registered with the calls production uses — AddStrataraAggregateGrains,
AddStrataraProjectionGrains, AddStrataraSagaGrains, AddStrataraDurableTimers,
AddStrataraOrleansCommandDispatcher — and run in the same grains, through the same mediator
pipeline, reading the store in commit order from a checkpoint.
Example
await using var host = await ExecutionModelTestHost.CreateAsync(services => services
.AddAggregatesFromAssemblyContaining<Account>()
.AddCommandHandlersFromAssemblyContaining<OpenAccountHandler>()
.AddProjectionsFromAssemblyContaining<BalanceProjection>()
.AddStrataraAggregateGrains()
.AddStrataraProjectionGrains());
await host.DispatchAsync(new OpenAccount(accountId, 100m)); // runs in the account's activation
await host.WaitForReadersAsync(); // every reader is at the store's head
Assert.Equal(100m, balances[accountId]);
Contents
ExecutionModelTestHost—CreateAsync(configure, options),DispatchAsync,WaitForReadersAsync,Timers,SeedAtHeadAsync,ResetAsync, the presetSessionandServices.IAsyncDisposable.ExecutionModelTestHostOptions— the periods (PollInterval250 ms,ReminderPeriod1 s,IntentGrace2 s,DrainPollingInterval1 s), the partition count (4), the start timeout, andBeforeStart, which runs before the silo starts — where a test appends history and seeds the readers at its head, as a deployment does while no silo runs. A value a test sets through a registration's own settings wins over the host's.StrataraTestReadDbContext— the read context that holds the checkpoints.
Share a host across a test class
Creating a host takes a few seconds. Share one through a class fixture and reset it between tests where one must not see another's state:
public sealed class ExecutionModelFixture : IAsyncLifetime
{
public ExecutionModelTestHost Host { get; private set; } = null!;
public async ValueTask InitializeAsync() =>
Host = await ExecutionModelTestHost.CreateAsync(services => services /* the roles */);
public ValueTask DisposeAsync() => Host.DisposeAsync();
}
ResetAsync runs the execution model's reset port on this host, where the silo keeps running: the timers
and the grain directory's entries go, and every registered reader is put at the store's head. The next
test's facts are applied, the last test's are not applied a second time, and WaitForReadersAsync returns
at once. The read models themselves are not emptied — empty or rebuild them in the fixture where a test
needs them clean.
Where the host stops
- One silo. Membership, reminders and the directory are in memory and not shared. What happens across silos — a kill, a role split, a takeover — is an integration test against real infrastructure.
- Test projects only. Referencing the package from a project that is not a test project fails
the build with
STRATARA1001;StrataraAllowTestSupportOutsideTests=trueopts out, as the sample does.CreateAsyncrefuses to run whereDOTNET_ENVIRONMENTorASPNETCORE_ENVIRONMENTstates an environment other thanDevelopment.
Dependencies
Stratara.Orleans,Stratara.Orleans.EntityFrameworkCore,Stratara.Testing.EntityFrameworkCoreMicrosoft.Orleans.Server,Microsoft.Extensions.Hosting
| 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.Hosting (>= 10.0.11)
- Microsoft.Orleans.Server (>= 10.3.1 && < 11.0.0)
- Stratara.Orleans (>= 4.4.4)
- Stratara.Orleans.EntityFrameworkCore (>= 4.4.4)
- Stratara.Testing.EntityFrameworkCore (>= 4.4.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
A one-fix release. On the Redis-backed replay state, a host could report a replay still active after it had ended
it, holding publication back for up to one refresh interval. Nothing else changes; no configuration or migration is
needed.
### Fixed
- **A host no longer reports a replay active after it ended the replay itself.** On the Redis-backed replay state, a
refresh that had read the marking just before the host's own deactivation could compare its generation before the
deactivation and write the field after it, leaving `IsReplayActive` true — and publication held back — until the
next refresh (`ProjectionReplay:RefreshSeconds`, default 5). The comparison and the write are now one step with the
transition. Present since 4.4.2.