xunit
SKILL.md
xUnit Skill
xUnit is the testing framework for VanDaemon. Tests follow the Arrange-Act-Assert pattern with FluentAssertions for readable assertions and Moq for mocking dependencies. All test projects use the naming convention {Project}.Tests.
Quick Start
Service Test Pattern
public class TankServiceTests
{
private readonly Mock<ILogger<TankService>> _loggerMock = new();
private readonly Mock<ISensorPlugin> _sensorMock = new();
[Fact]
public async Task GetAllTanksAsync_ReturnsOnlyActiveTanks()
{
// Arrange
var service = new TankService(_loggerMock.Object, _sensorMock.Object);
// Act
var result = await service.GetAllTanksAsync();
// Assert
result.Should().NotBeNull();
result.Should().AllSatisfy(t => t.IsActive.Should().BeTrue());
}
}
Testing with JsonFileStore
[Fact]
public async Task SaveAsync_PersistsDataToFile()
{
// Arrange - use temp directory for isolation
var tempPath = Path.Combine(Path.GetTempPath(), $"vandaemon-tests-{Guid.NewGuid()}");
var loggerMock = new Mock<ILogger<JsonFileStore>>();
var fileStore = new JsonFileStore(loggerMock.Object, tempPath);
try
{
// Act
await fileStore.SaveAsync("tanks", testTanks);
var loaded = await fileStore.LoadAsync<List<Tank>>("tanks");
// Assert
loaded.Should().BeEquivalentTo(testTanks);
}
finally
{
Directory.Delete(tempPath, recursive: true);
}
}
Key Concepts
| Concept | Usage | Example |
|---|---|---|
[Fact] |
Single test case | [Fact] public async Task Method_Condition_Result() |
[Theory] |
Parameterized tests | [Theory] [InlineData(0)] [InlineData(100)] |
[Collection] |
Shared test context | [Collection("Database")] |
| FluentAssertions | Readable assertions | result.Should().HaveCount(3) |
| Moq Setup | Define mock behavior | mock.Setup(x => x.Method()).ReturnsAsync(value) |
Common Patterns
Testing Async Methods with CancellationToken
When: Testing any async service method.
[Fact]
public async Task GetTankLevelAsync_PassesCancellationToken()
{
var cts = new CancellationTokenSource();
_sensorMock.Setup(x => x.ReadValueAsync(It.IsAny<string>(), cts.Token))
.ReturnsAsync(75.0);
var result = await _service.GetTankLevelAsync(tankId, cts.Token);
_sensorMock.Verify(x => x.ReadValueAsync(It.IsAny<string>(), cts.Token), Times.Once);
}
Testing Collections
result.Should().HaveCount(3);
result.Should().ContainSingle(t => t.Type == TankType.FreshWater);
result.Should().AllSatisfy(t => t.IsActive.Should().BeTrue());
result.Should().BeInAscendingOrder(t => t.Name);
Running Tests
dotnet test VanDaemon.sln # All tests
dotnet test --filter "FullyQualifiedName~TankService" # Specific class
dotnet test --verbosity normal # See test output
dotnet test --collect:"XPlat Code Coverage" # With coverage
See Also
Related Skills
- See the moq skill for mocking patterns
- See the fluent-assertions skill for assertion syntax
- See the dotnet skill for build/run commands
Weekly Installs
1
Repository
stuartf303/vandaemonGitHub Stars
1
First Seen
Mar 1, 2026
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
continue1
kimi-cli1