Skip to main content
ClaudeWave
Skill64 estrellas del repoactualizado 22d ago

dotnet-integration-testing

Configures integration tests with WebApplicationFactory and Testcontainers. Provides test database setup, authentication helpers, and utilities for testing API endpoints with real dependencies.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/ronnythedev/dotnet-clean-architecture-skills /tmp/dotnet-integration-testing && cp -r /tmp/dotnet-integration-testing/skills/22-dotnet-integration-testing ~/.claude/skills/dotnet-integration-testing
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Integration Test Setup

## Overview

Integration tests verify the full request pipeline:

- **WebApplicationFactory** - In-memory test server
- **Testcontainers** - Real PostgreSQL in Docker
- **Respawn** - Fast database cleanup between tests
- **Authentication helpers** - Test with different users/roles

## Quick Reference

| Component | Purpose |
|-----------|---------|
| `IntegrationTestWebAppFactory` | Custom test server factory |
| `BaseIntegrationTest` | Base class for all tests |
| `Respawner` | Database cleanup utility |
| `TestAuthHandler` | Fake authentication handler |

---

## Test Project Structure

```
tests/
└── {name}.Api.IntegrationTests/
    ├── Infrastructure/
    │   ├── IntegrationTestWebAppFactory.cs
    │   ├── BaseIntegrationTest.cs
    │   ├── TestAuthHandler.cs
    │   └── FakeUserContext.cs
    ├── {Feature}/
    │   ├── Create{Entity}Tests.cs
    │   └── Get{Entity}Tests.cs
    └── {name}.Api.IntegrationTests.csproj
```

---

## Template: Test Project File

```xml
<!-- tests/{name}.Api.IntegrationTests/{name}.Api.IntegrationTests.csproj -->
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="FluentAssertions" Version="6.12.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
    <PackageReference Include="Respawn" Version="6.1.0" />
    <PackageReference Include="Testcontainers.PostgreSql" Version="3.6.0" />
    <PackageReference Include="xunit" Version="2.6.2" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\..\src\{name}.api\{name}.api.csproj" />
    <ProjectReference Include="..\..\src\{name}.infrastructure\{name}.infrastructure.csproj" />
  </ItemGroup>

</Project>
```

---

## Template: WebApplicationFactory

```csharp
// tests/{name}.Api.IntegrationTests/Infrastructure/IntegrationTestWebAppFactory.cs
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Testcontainers.PostgreSql;
using {name}.infrastructure;

namespace {name}.Api.IntegrationTests.Infrastructure;

public class IntegrationTestWebAppFactory 
    : WebApplicationFactory<Program>, IAsyncLifetime
{
    private readonly PostgreSqlContainer _dbContainer = new PostgreSqlBuilder()
        .WithImage("postgres:15-alpine")
        .WithDatabase("testdb")
        .WithUsername("postgres")
        .WithPassword("postgres")
        .Build();

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureTestServices(services =>
        {
            // ═══════════════════════════════════════════════════════════════
            // REPLACE DATABASE WITH TEST CONTAINER
            // ═══════════════════════════════════════════════════════════════
            
            services.RemoveAll(typeof(DbContextOptions<ApplicationDbContext>));

            services.AddDbContext<ApplicationDbContext>(options =>
            {
                options.UseNpgsql(_dbContainer.GetConnectionString());
            });

            // ═══════════════════════════════════════════════════════════════
            // REPLACE AUTHENTICATION WITH TEST HANDLER
            // ═══════════════════════════════════════════════════════════════
            
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = TestAuthHandler.SchemeName;
                options.DefaultChallengeScheme = TestAuthHandler.SchemeName;
            })
            .AddScheme<TestAuthSchemeOptions, TestAuthHandler>(
                TestAuthHandler.SchemeName,
                options => { });

            // ═══════════════════════════════════════════════════════════════
            // REPLACE EXTERNAL SERVICES WITH FAKES
            // ═══════════════════════════════════════════════════════════════
            
            // services.RemoveAll<IEmailService>();
            // services.AddSingleton<IEmailService, FakeEmailService>();
        });

        builder.UseEnvironment("Testing");
    }

    public async Task InitializeAsync()
    {
        await _dbContainer.StartAsync();
        
        // Apply migrations
        using var scope = Services.CreateScope();
        var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
        await dbContext.Database.MigrateAsync();
    }

    public new async Task DisposeAsync()
    {
        await _dbContainer.StopAsync();
    }
}
```

---

## Template: Test Authentication Handler

```csharp
// tests/{name}.Api.IntegrationTests/Infrastructure/TestAuthHandler.cs
using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace {name}.Api.IntegrationTests.Infrastructure;

public class TestAuthSchemeOptions : AuthenticationSchemeOptions
{
    public Guid? UserId { get; set; }
    public string? Email { get; set; }
    public string[]? Roles { get; set; }
    public string[]? Permissions { get; set; }
}

public class TestAuthHandler : AuthenticationHandler<TestAuthSchemeOptions>
{
    public const string SchemeName = "TestScheme";
    public const string TestUserIdHeader = "X-Test-User-Id";
    public const string TestUserEmailHeader = "X-Test-User-Email";
dotnet-clean-architectureSkill

Scaffolds a complete .NET solution following Clean Architecture principles with proper layer separation (API, Application, Domain, Infrastructure). Creates project structure, dependency injection setup, and cross-cutting concerns configuration.

dotnet-cqrs-command-generatorSkill

Generates CQRS Commands with Handlers, Validators, and Request DTOs following Clean Architecture patterns. Commands represent actions that modify state and return Result types for proper error handling.

dotnet-cqrs-query-generatorSkill

Generates CQRS Queries with Handlers and Response DTOs for read operations. Uses Dapper for optimized read queries, bypassing the domain model for better performance.

dotnet-domain-entity-generatorSkill

Generates Domain Entities following DDD principles with factory methods, private setters, domain events, and proper encapsulation. Supports aggregate roots, child entities, and value objects.

dotnet-repository-patternSkill

Generates Repository interfaces and implementations following the Repository pattern. Provides data access abstraction for aggregate roots with EF Core implementations.

dotnet-ef-core-configurationSkill

Generates Entity Framework Core configurations using Fluent API. Maps domain entities to database tables with proper relationships, constraints, and conventions.

dotnet-legacy-api-controllersSkill

Generates RESTful API Controllers with proper routing, versioning, authorization, and MediatR integration. Follows REST conventions and Clean Architecture patterns.

dotnet-minimal-api-endpointsSkill

Generates Minimal API endpoints following Microsoft's recommended approach. Creates fast, testable HTTP APIs with minimal code using MapGet/MapPost/MapPut/MapDelete. Preferred over controller-based APIs for new projects.