From dotnet-pilot-core
.NET testing patterns — xUnit conventions, integration tests with WebApplicationFactory, mocking strategies, and test organization.
npx claudepluginhub zdanovichnick/dotnet-pilot --plugin dotnet-pilot-coreThis skill uses the workspace's default tool permissions.
Reference for test generation. Used by `dnp-test-writer` and `dnp-planner`.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Reference for test generation. Used by dnp-test-writer and dnp-planner.
tests/
├── MyApp.UnitTests/ # Fast, isolated, mock dependencies
│ ├── Services/
│ │ └── UserServiceTests.cs
│ └── Domain/
│ └── UserTests.cs
├── MyApp.IntegrationTests/ # Slower, real dependencies
│ ├── Api/
│ │ └── UserEndpointTests.cs
│ └── Infrastructure/
│ └── UserRepositoryTests.cs
└── MyApp.ArchitectureTests/ # Optional: enforce architecture rules
└── LayerDependencyTests.cs
public class UserServiceTests
{
private readonly Mock<IUserRepository> _repo;
private readonly UserService _sut; // system under test
public UserServiceTests()
{
_repo = new Mock<IUserRepository>();
_sut = new UserService(_repo.Object);
}
}
MethodName_StateUnderTest_ExpectedBehavior
[Fact]
public async Task GetByIdAsync_WhenUserExists_ReturnsUser() { }
[Fact]
public async Task GetByIdAsync_WhenUserNotFound_ReturnsNull() { }
[Theory]
[InlineData("")]
[InlineData(null)]
public async Task CreateAsync_WithInvalidEmail_ThrowsValidationException(string? email) { }
public class DatabaseTests : IClassFixture<DatabaseFixture>
{
private readonly DatabaseFixture _fixture;
public DatabaseTests(DatabaseFixture fixture) => _fixture = fixture;
}
public class UserEndpointTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly HttpClient _client;
public UserEndpointTests(WebApplicationFactory<Program> factory)
{
_client = factory.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
// Replace real DB with in-memory
services.RemoveAll<DbContextOptions<ApplicationDbContext>>();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseInMemoryDatabase("TestDb"));
});
}).CreateClient();
}
[Fact]
public async Task CreateUser_Returns201WithLocation()
{
var request = new { Name = "Test", Email = "test@example.com" };
var response = await _client.PostAsJsonAsync("/api/users", request);
response.StatusCode.Should().Be(HttpStatusCode.Created);
response.Headers.Location.Should().NotBeNull();
}
}
| Feature | Moq | NSubstitute | FakeItEasy |
|---|---|---|---|
| Syntax | mock.Setup(x => x.Method()).Returns(value) | sub.Method().Returns(value) | A.CallTo(() => fake.Method()).Returns(value) |
| Verify | mock.Verify(x => x.Method(), Times.Once) | sub.Received(1).Method() | A.CallTo(() => fake.Method()).MustHaveHappenedOnceExactly() |
| Popularity | Most popular | Growing | Niche |
var fixture = new Fixture();
var user = fixture.Create<User>();
var user = new UserBuilder().WithEmail("test@example.com").Build();