.claude/skills/gen-test-class/SKILL.md
Use when creating a test class for a source file or when no tests exist yet for a class. Generates a convention-compliant xUnit test class covering all six coverage categories (happy path, validation, not-found, cancellation, invariants, round-trip). Pairs with gen-gherkin-feature (upstream criteria) and gen-use-case (upstream model). Also invoke when the user mentions: write tests, add unit tests, test class, xUnit tests for, test coverage. Domain: Testing, Code Generation. Level: Intermediate.
npx skillsauth add klod68/littlerae gen-test-classInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate a complete test class for the source file I am currently pointing at.
Produce tests for all six coverage categories — do not omit any:
${1:SourceProject}/X.cs → ${2:TestProject}/XTests.cs{SourceClass}Testsnamespace ${3:RootNamespace}.Tests.{SubNamespace};
/// <summary>Tests for {SourceClass}.</summary>
public class {SourceClass}Tests
{
#region Test Implementation // expose protected members if needed
#endregion
#region Constructor Tests
#endregion
#region Default Values Tests
#endregion
#region {MethodGroup} Tests // one region per public method group
#endregion
#region Helper Methods // reusable mock setup and factory methods
#endregion
}
{Method}_{Scenario}_{ExpectedBehavior}
Examples:
Constructor_NullLogger_ThrowsArgumentNullExceptionGetById_ValidId_ReturnsExpectedEntityFindAll_EmptyRepository_ReturnsEmptyCollectionSave_CancellationRequested_PropagatesToken// Single case
[Fact]
public void Method_Scenario_ExpectedBehavior() { }
// Parameterized
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public void Method_InvalidInput_Throws(string? input) { }
// Exception assertion
var act = () => new MyClass(null!);
act.Should().Throw<ArgumentNullException>().WithParameterName("paramName");
// Async exception
var act = async () => await sut.DoAsync(null!, ct);
await act.Should().ThrowAsync<ArgumentNullException>();
// Happy path
result.Should().NotBeNull();
result.Should().Be(expected);
collection.Should().HaveCount(3).And.Contain(x => x.Id == expectedId);
CreateMockLogger(), CreateSut()) to avoid setup duplication.CancellationToken propagation: verify the mock received the same token the caller passed.Always use explicit section comments:
[Fact]
public async Task SaveAsync_ValidEntity_PersistsAndReturnsVoid()
{
// Arrange
var entity = new OrderBuilder().WithDefaults().Build();
_repositoryMock.Setup(r => r.SaveAsync(entity, It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
// Act
await _sut.SaveAsync(entity, CancellationToken.None);
// Assert
_repositoryMock.Verify(r => r.SaveAsync(entity, It.IsAny<CancellationToken>()), Times.Once);
}
if, for, or switch inside test methods — use [Theory] instead.| Mock (external dependency) | Use Real (internal type) |
|---|---|
| IDbConnection, IDbCommand | Domain entities, value objects |
| HttpClient, IHttpClientFactory | Mappers, formatters, validators |
| ILogger<T> | Configuration classes |
| IFileSystem (abstraction) | DTOs, records, enums |
CreateSut()) to centralize mock setup and avoid duplication.For abstract base classes, create a private test subclass inside the test class:
public class DataProviderBaseTests
{
private sealed class TestProvider : DataProviderBase
{
public TestProvider(string connectionString)
: base(connectionString) { }
// Minimal implementation of abstract members
public override Task<T?> GetByIdAsync<T>(int id, CancellationToken ct) where T : default
=> Task.FromResult(default(T));
}
[Fact]
public void Constructor_NullConnection_ThrowsArgumentException()
{
var act = () => new TestProvider(null!);
act.Should().Throw<ArgumentException>();
}
}
private sealed inside the test class — never shared.InternalsVisibleTo in the library .csproj to test internal abstract types.Run to verify compilation and execution:
dotnet test ${4:Solution.sln} --filter "FullyQualifiedName~{SourceClass}Tests"
tools
Use when cross-cutting concerns (logging, metrics, validation, authorization) are tangled into command handlers or service methods, when building database command pipelines with reorderable concerns, or when HTTP client pipelines or message handlers need composable, independently-replaceable processing stages. Covers ICommandInterceptor interface, InterceptorPipeline with reverse-chain construction, zero-cost Empty sentinel to skip overhead when no interceptors are registered, and ConfigureAwait(false) discipline for library code. Domain: Architecture, Cross-Cutting Concerns. Level: Intermediate. Tags: interceptor, pipeline, middleware, decorator, cross-cutting-concerns.
development
Use when writing integration tests for Razor Pages, MVC, or Minimal API applications to validate routing, middleware, page rendering, and HTTP behavior without a browser or live server, or when adding fast smoke tests to a CI pipeline. Covers WebApplicationFactory<Program> setup with public partial class Program, in-memory test server, AngleSharp HTML parsing, CSS selector assertions, redirect and status code testing, and a shared static fixture pattern for minimal per-test startup overhead. Domain: Testing, ASP.NET Core. Level: Intermediate. Tags: integration-testing, webapplicationfactory, razor-pages, anglesharp, http-testing.
development
Use when designing indexes for new tables, diagnosing slow queries that are not using indexes efficiently, reviewing index fragmentation and maintenance, or when the current indexing strategy results in key lookups, table scans, or missing index warnings. Covers clustered index key selection (narrow, unique, ever-increasing), non-clustered index design for query patterns, covering indexes with INCLUDE columns, filtered indexes for subset queries, composite index column ordering, DMV-based monitoring for missing and unused indexes, and rebuild vs reorganize maintenance thresholds. Domain: Database, Performance. Level: Intermediate. Tags: index, sql-server, covering-index, filtered-index, performance, dmv, maintenance.
development
Use when building a searchable in-memory catalog or registry for documentation sites, admin panels, or type/API browsers where you need keyword matching, fuzzy search, and ranked results without an external search engine or database. Covers RegistryService with weighted scoring across name, description, keywords, and method names; Levenshtein fuzzy matching; synonym expansion; category and subcategory filtering; and singleton DI registration for datasets of hundreds to low thousands of items. Domain: Search, Data Access Patterns. Level: Intermediate. Tags: search, registry, fuzzy-matching, in-memory, catalog, filtering.