testing-dotnet
| Type | Skill |
| Plugin | awl-testing · v0.0.27 |
| Invoke | /awl-testing:testing-dotnet |
| Tools | Read, Write, Edit, Bash, Glob, Grep |
| Source | plugins/awl-testing/skills/testing-dotnet/SKILL.md |
When Claude uses it
Section titled “When Claude uses it”Writes and debugs .NET tests using xUnit, Moq, FluentAssertions, and Testcontainers. Use when “write dotnet tests”, “xunit test”, “mock with moq”, “test c# code”, “fluentassertions”, “testcontainers”, “integration test c#”, “api test dotnet”, “fix dotnet test”, “debug test failure”, “test fixture setup”, “theory test”, “fact test”.
Trigger phrases: write dotnet tests · xunit test · mock with moq · test c# code · fluentassertions · testcontainers · integration test c# · api test dotnet · fix dotnet test · debug test failure · test fixture setup · theory test · fact test
Definition
Section titled “Definition”Quick Start
Section titled “Quick Start”[Fact]public void CreateUser_WithoutEmail_ShouldThrow(){ // Arrange var service = new UserService();
// Act Action act = () => service.CreateUser(new UserData { Name = "Alice" });
// Assert act.Should().Throw<ArgumentException>().WithMessage("*email*");}Run tests:
dotnet testdotnet test --filter "FullyQualifiedName~UserService"When to Use
Section titled “When to Use”| Task | This Skill Helps With |
|---|---|
| Unit tests | Testing isolated components with mocks |
| Integration tests | Testing with databases, EF Core |
| API tests | Testing ASP.NET Core endpoints |
| Test failures | Debugging red tests, fixing assertions |
| Test setup | Fixtures, lifecycle, IAsyncLifetime |
Naming Conventions
Section titled “Naming Conventions”Classes: <TypeUnderTest>Tests (e.g., UserServiceTests)
Methods: <Method>_<State>_<Expected> (e.g., CreateUser_WithoutEmail_ShouldThrow)
Projects: Tests.Unit, Tests.Integration, Tests.Api
Core Patterns
Section titled “Core Patterns”Unit Test with Moq
Section titled “Unit Test with Moq”[Fact]public async Task GetUserById_ExistingUser_ReturnsUser(){ // Arrange var mockRepo = new Mock<IUserRepository>(); mockRepo.Setup(r => r.GetByIdAsync(1)) .ReturnsAsync(new User { Id = 1, Name = "John" }); var service = new UserService(mockRepo.Object);
// Act var user = await service.GetUserByIdAsync(1);
// Assert user.Should().NotBeNull(); user.Name.Should().Be("John"); mockRepo.Verify(r => r.GetByIdAsync(1), Times.Once);}Parameterized Test
Section titled “Parameterized Test”[Theory][InlineData(2, 3, 5)][InlineData(-1, 1, 0)][InlineData(0, 0, 0)]public void Add_ReturnsExpectedResult(int a, int b, int expected){ // Arrange var calc = new Calculator();
// Act var result = calc.Add(a, b);
// Assert result.Should().Be(expected);}Exception Testing
Section titled “Exception Testing”[Fact]public void Process_NullInput_ThrowsArgumentNull(){ // Arrange var service = new MyService();
// Act Action act = () => service.ProcessData(null);
// Assert act.Should().Throw<ArgumentNullException>().WithMessage("*data*");}Async Testing
Section titled “Async Testing”[Fact]public async Task ProcessAsync_ValidInput_Succeeds(){ // Arrange var service = new MyService();
// Act var result = await service.ProcessAsync(validData);
// Assert result.Should().NotBeNull();}Setup & Teardown
Section titled “Setup & Teardown”Per-Test (Constructor/Dispose)
Section titled “Per-Test (Constructor/Dispose)”public class UserServiceTests : IDisposable{ private readonly UserService _service; private readonly Mock<IUserRepository> _mockRepo;
public UserServiceTests() { _mockRepo = new Mock<IUserRepository>(); _service = new UserService(_mockRepo.Object); }
public void Dispose() => _service?.Dispose();}Async Lifecycle
Section titled “Async Lifecycle”public class DatabaseTests : IAsyncLifetime{ private TestDatabase _db;
public async Task InitializeAsync() { _db = new TestDatabase(); await _db.ConnectAsync(); }
public async Task DisposeAsync() => await _db.CleanupAsync();}Shared Fixture
Section titled “Shared Fixture”public class DatabaseFixture : IAsyncLifetime{ public DbContext DbContext { get; private set; }
public async Task InitializeAsync() { DbContext = await CreateDbContextAsync(); await DbContext.Database.MigrateAsync(); }
public async Task DisposeAsync() => await DbContext.DisposeAsync();}
public class MyTests : IClassFixture<DatabaseFixture>{ private readonly DatabaseFixture _fixture; public MyTests(DatabaseFixture fixture) => _fixture = fixture;}Common Assertions (FluentAssertions)
Section titled “Common Assertions (FluentAssertions)”result.Should().Be(expected);result.Should().NotBeNull();list.Should().NotBeEmpty();list.Should().HaveCount(3);list.Should().Contain(item);list.Should().OnlyContain(x => x.IsActive);str.Should().StartWith("Hello");str.Should().Contain("world");Troubleshooting
Section titled “Troubleshooting”Test Not Running
Section titled “Test Not Running”# Check if discovereddotnet test --list-tests
# Rebuilddotnet clean && dotnet build
# Check filterdotnet test --filter "FullyQualifiedName~ClassName"Async Test Hangs
Section titled “Async Test Hangs”// BAD: Blocks threadvar result = service.GetAsync().Result;
// GOOD: Await properlyvar result = await service.GetAsync();Mock Not Returning Value
Section titled “Mock Not Returning Value”// BAD: Wrong setupmockRepo.Setup(r => r.GetById(1));
// GOOD: Return valuemockRepo.Setup(r => r.GetById(1)).Returns(user);mockRepo.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(user);FluentAssertions Not Found
Section titled “FluentAssertions Not Found”dotnet add package FluentAssertionsThen add using FluentAssertions; to test file.
Best Practices
Section titled “Best Practices”- AAA Pattern - Always Arrange-Act-Assert with comments
- One assertion concept - Test one behavior per method
- Descriptive names - Method name explains the scenario
- Independent tests - No shared state, no order dependency
- Async all the way - Never
.Resultor.Wait() - FluentAssertions - More readable than xUnit assertions
- Fakes over mocks - When simpler implementations work
Running Tests
Section titled “Running Tests”# All testsdotnet test
# Specific projectdotnet test Tests.Unit/Tests.Unit.csproj
# Filter by namedotnet test --filter "FullyQualifiedName~UserService"
# With coveragedotnet test /p:CollectCoverage=true
# Verbose outputdotnet test --logger:"console;verbosity=detailed"References
Section titled “References”For advanced patterns and complete examples:
- UNIT_TESTING.md - xUnit features, fixtures, parameterized tests
- INTEGRATION_TESTING.md - Database testing, EF Core patterns
- API_TESTING.md - WebApplicationFactory, endpoint testing
- TESTCONTAINERS.md - Docker containers for tests

