Test a command
Goal: verify a command does the right thing — succeeds when it should, rejects bad input, refuses an unauthorized caller — without standing up a web server or a database.
The real pipeline, in-process
Section titled “The real pipeline, in-process”CommandScenario<TCommand> drives a command through the same pipeline production uses: validation filters, authorization filters, and the handler all run, nothing is mocked by default. When the Chronicle testing package is referenced, it adds an in-memory event log automatically, so you can also assert on what was appended.
Reference Cratis.Testing (the meta-package) in your spec project.
-
Instantiate the scenario as a field, then
Executethe command and assert on theCommandResult:public class when_registering_an_author{readonly CommandScenario<RegisterAuthor> _scenario = new();[Fact]public async Task should_succeed(){var result = await _scenario.Execute(new RegisterAuthor(AuthorId.New(), "Ada Lovelace"));result.ShouldBeSuccessful();}} -
Check validation without running the handler using
Validate:[Fact]public async Task should_reject_a_blank_name(){var result = await _scenario.Validate(new RegisterAuthor(AuthorId.New(), string.Empty));result.ShouldHaveValidationErrors();} -
Register stubs or fakes the handler depends on through
Services, in the test constructor:public when_registering_an_author() =>_scenario.Services.AddSingleton(_someDependency);
The CommandResult assertion helpers — ShouldBeSuccessful, ShouldHaveValidationErrors, ShouldHaveValidationErrorFor("…"), ShouldNotBeAuthorized, and more — read like sentences and print the failure reasons when they fail.
See also
Section titled “See also”- Command Scenarios — the full API and every assertion helper.
- Testing — the testing packages and the Chronicle in-memory event log.