Skip to main content

testing-guide

Write tests for an FSH feature — xUnit + Shouldly + NSubstitute + AutoFixture, with naming and AAA conventions. Use when adding unit/handler/validator/entity tests. Full rules in .agents/rules/testing.md + integration-testing.md.

Informações da origem

Repositório
fullstackhero/dotnet-starter-kit
Última atividade na origem
25 de setembro de 2026 às 01:46
Idioma detectado do SKILL.md
inglês
Estrelas
6.806
Forks
2.002

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
testing-guide
description
Write tests for an FSH feature — xUnit + Shouldly + NSubstitute + AutoFixture, with naming and AAA conventions. Use when adding unit/handler/validator/entity tests. Full rules in .agents/rules/testing.md + integration-testing.md.
# Testing Guide Stack: **xUnit** + **Shouldly** (`.ShouldBe`) + **NSubstitute** (`Substitute.For<>`) + **AutoFixture** (`new Fixture()`). **Not** Moq, **not** FluentAssertions. Detailed conventions + integration-test gotchas live in `.agents/rules/testing.md` and `.agents/rules/integration-testing.md`. ## Conventions - Test class: `public sealed class {Sut}Tests`; SUT field named `_sut`. - Method name: **`MethodName_Should_ExpectedBehavior[_When_Condition]`**. - Arrange-Act-Assert with `// Arrange` / `// Act` / `// Assert`; group with `#region` (Happy Path / Guards / Edge Cases). - Mocks via `Substitute.For<IService>()`; assert calls with `.Received(1).X(arg, Arg.Any<CancellationToken>())`. - When asserting a forwarded `CancellationToken`, assert the **specific** token, not the default (NSubstitute fills optional params with `default`). ## Handler test ```csharp public sealed class Create{Entity}CommandHandlerTests { private readonly {X}DbContext _db; // or Substitute.For<IService>() for service deps private readonly Create{Entity}CommandHandler _sut; private readonly IFixture _fixture = new Fixture(); public Create{Entity}CommandHandlerTests() { _db = /* in-memory or test DbContext */; _sut = new Create{Entity}CommandHandler(_db); } [Fact] public async Task Handle_Should_PersistEntity_And_ReturnId() { // Arrange var command = new Create{Entity}Command(_fixture.Create<string>(), 9.99m, "USD"); // Act var id = await _sut.Handle(command, CancellationToken.None); // Assert id.ShouldNotBe(Guid.Empty); } } ``` Service-dependency example (NSubstitute): ```csharp _userService = Substitute.For<IUserService>(); // Act … then: await _userService.Received(1).ToggleStatusAsync(true, command.UserId, Arg.Any<CancellationToken>()); ``` ## Validator test ```csharp public sealed class Create{Entity}CommandValidatorTests { private readonly Create{Entity}CommandValidator _sut = new(); [Theory] [InlineData("")] public void Validate_Should_Fail_When_NameInvalid(string name) { var result = _sut.Validate(new Create{Entity}Command(name, 1m, "USD")); result.IsValid.ShouldBeFalse(); result.Errors.ShouldContain(e => e.PropertyName == nameof(Create{Entity}Command.Name)); } } ``` ## Entity / domain test (no mocks) ```csharp [Fact] public void Create_Should_RaiseCreatedEvent() { var entity = {Entity}.Create("Test", Money.Zero()); entity.Id.ShouldNotBe(Guid.Empty); entity.DomainEvents.ShouldContain(e => e is {Entity}CreatedDomainEvent); } ``` ## Architecture tests (guardrails — keep green) `Architecture.Tests` (NetArchTest) enforce: module boundaries (cross-module refs only via `.Contracts`), tenant-isolation rules, handlers `sealed`, and **every command/paginated-query handler has a validator**. Don't weaken these to make a change pass — fix the code. ## Integration tests `Integration.Tests` runs over real Postgres/Redis/RustFS via Testcontainers — **Docker required**. Set the Finbuckle tenant context inline, rewire `IStorageService` post-registration for RustFS (S3), force long-polling for SignalR. All detailed in `.agents/rules/integration-testing.md`. ## Run ```bash dotnet test src/Tests/{X}.Tests dotnet test src/Tests/Architecture.Tests dotnet test src/FSH.Starter.slnx --collect "XPlat Code Coverage" --settings coverage.runsettings ```
Ver no GitHub