home / skills / stuartf303 / sorcha / xunit
This skill helps you create and validate xUnit tests across multiple projects using FluentAssertions and Moq for reliable C# test coverage.
npx playbooks add skill stuartf303/sorcha --skill xunitReview the files below or copy the command above to add this skill to your agents.
---
name: xunit
description: |
Writes unit tests with xUnit framework across 30 test projects.
Use when: writing new tests, adding test coverage, creating integration tests, setting up test fixtures, or debugging test failures.
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, mcp__context7__resolve-library-id, mcp__context7__query-docs
---
# xUnit Skill
xUnit 2.9.3 is the testing framework for all 30 test projects in Sorcha. Tests use **FluentAssertions** for readable assertions and **Moq** for mocking. All tests follow strict `MethodName_Scenario_ExpectedBehavior` naming.
## Quick Start
### Unit Test Structure
```csharp
// SPDX-License-Identifier: MIT
// Copyright (c) 2025 Sorcha Contributors
public class WalletManagerTests
{
private readonly Mock<IRepository<Wallet>> _mockRepository;
private readonly WalletManager _sut;
public WalletManagerTests()
{
_mockRepository = new Mock<IRepository<Wallet>>();
_sut = new WalletManager(_mockRepository.Object);
}
[Fact]
public async Task CreateAsync_ValidWallet_ReturnsSuccess()
{
// Arrange
var wallet = new Wallet { Name = "Test" };
_mockRepository.Setup(r => r.AddAsync(wallet)).ReturnsAsync(wallet);
// Act
var result = await _sut.CreateAsync(wallet);
// Assert
result.IsSuccess.Should().BeTrue();
result.Value.Should().Be(wallet);
}
}
```
### Theory with InlineData
```csharp
[Theory]
[InlineData(12)]
[InlineData(15)]
[InlineData(18)]
[InlineData(21)]
[InlineData(24)]
public void GenerateMnemonic_ValidWordCount_ReturnsCorrectLength(int wordCount)
{
var result = _keyManager.GenerateMnemonic(wordCount);
result.IsSuccess.Should().BeTrue();
result.Value!.Split(' ').Should().HaveCount(wordCount);
}
```
## Key Concepts
| Concept | Usage | Example |
|---------|-------|---------|
| `[Fact]` | Single test case | `[Fact] public void Method_Test() {}` |
| `[Theory]` | Parameterized tests | `[Theory] [InlineData(1)] public void Method(int x) {}` |
| `IClassFixture<T>` | Per-class shared state | `class Tests : IClassFixture<DbFixture>` |
| `ICollectionFixture<T>` | Cross-class shared state | `[Collection("Db")] class Tests` |
| `IAsyncLifetime` | Async setup/teardown | `Task InitializeAsync()`, `Task DisposeAsync()` |
## Common Patterns
### Exception Testing
```csharp
[Fact]
public void Constructor_NullRepository_ThrowsArgumentNullException()
{
var act = () => new WalletManager(null!);
act.Should().Throw<ArgumentNullException>()
.WithParameterName("repository");
}
[Fact]
public async Task ProcessAsync_InvalidData_ThrowsWithMessage()
{
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
() => _processor.ProcessAsync(invalidContext));
exception.Message.Should().Contain("validation failed");
}
```
### Async Test Pattern
```csharp
[Fact]
public async Task ExecuteAsync_ValidBlueprint_CompletesSuccessfully()
{
// Arrange
var blueprint = CreateTestBlueprint();
// Act
var result = await _engine.ExecuteAsync(blueprint);
// Assert
result.Success.Should().BeTrue();
result.ProcessedData.Should().ContainKey("output");
}
```
## See Also
- [patterns](references/patterns.md) - Test patterns and anti-patterns
- [workflows](references/workflows.md) - Test workflows and fixtures
## Related Skills
- See the **fluent-assertions** skill for assertion patterns
- See the **moq** skill for mocking dependencies
- See the **entity-framework** skill for database testing with InMemory provider
- See the **postgresql** skill for Testcontainers integration tests
## Documentation Resources
> Fetch latest xUnit documentation with Context7.
**How to use Context7:**
1. Use `mcp__context7__resolve-library-id` to search for "xunit"
2. Query with `mcp__context7__query-docs` using the resolved library ID
**Library ID:** `/xunit/xunit.net` _(875 code snippets, High reputation)_
**Recommended Queries:**
- "xUnit Theory InlineData patterns"
- "IClassFixture ICollectionFixture shared context"
- "IAsyncLifetime async setup teardown"
- "xUnit parallel test execution configuration"This skill writes and organizes unit and integration tests using the xUnit framework across 30 C# test projects. It provides patterns, naming conventions, and common setups to produce consistent, readable, and maintainable tests for a decentralised Secure Data Governance and Disclosure System. The skill emphasizes FluentAssertions for assertions and Moq for mocking to keep tests expressive and focused.
The skill generates test code that follows the MethodName_Scenario_ExpectedBehavior naming convention and uses [Fact] for single cases and [Theory] with InlineData for parameterized cases. It scaffolds common test fixtures (IClassFixture, ICollectionFixture) and async lifecycle hooks (IAsyncLifetime) and applies common patterns for exception testing, async tests, and mocking repository or service dependencies. Tests use FluentAssertions for clear assertions and Moq setups to simulate dependencies.
Should I use [Fact] or [Theory]?
Use [Fact] for single-case assertions and [Theory] with InlineData for parameterized inputs to validate multiple scenarios in one test method.
When should I use IClassFixture vs ICollectionFixture?
Use IClassFixture for shared state scoped to a single test class. Use ICollectionFixture when multiple test classes need the same shared context, such as an integration database.
How do I test async methods reliably?
Write async test methods returning Task, use await for async calls, and implement IAsyncLifetime on fixtures for async setup and teardown to avoid race conditions.