mcpField
A
aspire-integration-testing

aspire-integration-testing

github.com/aaronontheweb测试与质量1.2k510 次安装今天更新
代码仓库

关于 aspire-integration-testing

面向 .NET Aspire 开发者的 xUnit 集成测试技能指南,适用于 ASP.NET Core 应用和分布式服务。它说明如何使用真实基础设施、动态端点发现和健康检查来构建测试。

主要功能

  1. 01使用 Aspire 编排测试服务
  2. 02通过 IAsyncLifetime 管理夹具生命周期
  3. 03动态发现服务端点
  4. 04使用真实数据库与容器基础设施
  5. 05涵盖 Playwright 和消息队列测试

适用场景

  1. 01测试 ASP.NET Core 与数据库集成
  2. 02验证微服务间通信
  3. 03运行带真实后端的 UI 测试

MCP 相关

指南提及 Aspire CLI 与 MCP 集成,可让 AI 助手查询应用的实时状态。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/aaronontheweb/dotnet-skills --skill aspire-integration-testing

安装后在 Claude Code 中输入/aspire-integration-testing确认已加载。

附带文件advanced-patterns.mdci-and-tooling.md

详细介绍

使用 .NET Aspire + xUnit 进行集成测试

何时使用此技能

在以下情况下使用此技能:

  • 为 .NET Aspire 应用编写集成测试
  • 使用真实数据库连接测试 ASP.NET Core 应用
  • 验证分布式应用中的服务间通信
  • 使用容器中的实际基础设施(SQL Server、Redis、消息队列)进行测试
  • 将 Playwright UI 测试与 Aspire 编排的服务结合使用
  • 使用适当的服务发现和网络配置测试微服务

参考文件

  • advanced-patterns.md:端点发现、数据库测试、Playwright、条件配置、Respawn、服务通信、消息队列
  • ci-and-tooling.md:CI/CD 集成、自定义资源等待器、结合 MCP 使用 Aspire CLI

核心原则

  1. 真实依赖项 - 通过 Aspire 使用实际基础设施(数据库、缓存),而非模拟对象
  2. 动态端口绑定 - 让 Aspire 动态分配端口(127.0.0.1:0),以避免冲突
  3. 夹具生命周期 - 使用 IAsyncLifetime 正确设置和清理测试夹具
  4. 端点发现 - 切勿硬编码 URL;在运行时从 Aspire 发现端点
  5. 并行隔离 - 使用 xUnit 集合控制测试并行化
  6. 运行状况检查 - 运行测试前始终等待服务就绪

测试架构概览

┌─────────────────┐                    ┌──────────────────────┐
│ xUnit test file │──uses────────────►│  AspireFixture       │
└─────────────────┘                    │  (IAsyncLifetime)    │
                                       └──────────────────────┘
                                               │
                                               │ starts
                                               ▼
                                    ┌───────────────────────────┐
                                    │  DistributedApplication   │
                                    │  (from AppHost)           │
                                    └───────────────────────────┘
                                               │ exposes
                                               ▼
                                  ┌──────────────────────────────┐
                                  │   Dynamic HTTP Endpoints     │
                                  └──────────────────────────────┘
                                               │ consumed by
                                               ▼
                                   ┌─────────────────────────┐
                                   │  HttpClient / Playwright│
                                   └─────────────────────────┘

必需的 NuGet 包

<ItemGroup>
  <PackageReference Include="Aspire.Hosting.Testing" Version="$(AspireVersion)" />
  <PackageReference Include="xunit" Version="*" />
  <PackageReference Include="xunit.runner.visualstudio" Version="*" />
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="*" />
</ItemGroup>

重要:集成测试的文件监视器修复

运行许多分别启动 IHost 的集成测试时,默认的 .NET 主机构建器会启用配置重载的文件监视器。这会耗尽 Linux 上的文件描述符限制。

在运行任何测试之前,将以下内容添加到测试项目中:

// TestEnvironmentInitializer.cs
using System.Runtime.CompilerServices;

namespace YourApp.Tests;

internal static class TestEnvironmentInitializer
{
    [ModuleInitializer]
    internal static void Initialize()
    {
        // Disable config file watching in test hosts
        // Prevents file descriptor exhaustion (inotify watch limit) on Linux
        Environment.SetEnvironmentVariable("DOTNET_HOSTBUILDER__RELOADCONFIGONCHANGE", "false");
    }
}

模式 1:基本 Aspire 测试夹具(现代 API)

using Aspire.Hosting;
using Aspire.Hosting.Testing;

public sealed class AspireAppFixture : IAsyncLifetime
{
    private DistributedApplication? _app;

    public DistributedApplication App => _app
        ?? throw new InvalidOperationException("App not initialized");

    public async Task InitializeAsync()
    {
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.YourApp_AppHost>([
                "YourApp:UseVolumes=false",
                "YourApp:Environment=IntegrationTest",
                "YourApp:Replicas=1"
            ]);

        _app = await builder.BuildAsync();

        using var startupCts = new CancellationTokenSource(TimeSpan.FromMinutes(10));
        await _app.StartAsync(startupCts.Token);

        using var healthCts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
        await _app.ResourceNotifications.WaitForResourceHealthyAsync("api", healthCts.Token);
    }

    public Uri GetEndpoint(string resourceName, string scheme = "https")
    {
        return _app?.GetEndpoint(resourceName, scheme)
            ?? throw new InvalidOperationException($"Endpoint for '{resourceName}' not found");
    }

    public async Task DisposeAsync()
    {
        if (_app is not null)
        {
            await _app.DisposeAsync();
        }
    }
}

模式 2:在测试中使用夹具

[CollectionDefinition("Aspire collection")]
public class AspireCollection : ICollectionFixture<AspireAppFixture> { }

[Collection("Aspire collection")]
public class IntegrationTests
{
    private readonly AspireAppFixture _fixture;

    public IntegrationTests(AspireAppFixture fixture)
    {
        _fixture = fixture;
    }

    [Fact]
    public async Task Application_ShouldStart()
    {
        var httpClient = _fixture.App.CreateHttpClient("yourapp");
        var response = await httpClient.GetAsync("/");
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }
}

有关端点发现、数据库测试、Playwright UI 测试、条件资源配置、Respawn 数据库重置、服务间通信和消息队列测试模式,请参阅 advanced-patterns.md。

常见模式汇总

模式用例
基本夹具简单 HTTP 端点测试
端点发现避免硬编码 URL
数据库测试验证数据访问层
Playwright 集成使用真实后端进行完整 UI 测试
配置覆盖特定于测试的设置
运行状况检查确保服务已就绪
服务通信测试分布式系统交互
消息队列测试验证异步消息传递

易错/不明显的提示

问题解决方案
测试立即超时调用 await _app.StartAsync() 并等待服务就绪
测试之间发生端口冲突使用 xUnit CollectionDefinition 共享夹具
因时序问题导致测试不稳定实现适当的运行状况检查轮询,而非使用 Task.Delay()
无法连接到 SQL Server通过 GetConnectionStringAsync() 动态获取连接字符串
并行测试相互干扰使用 [Collection] 特性按顺序运行相关测试
Aspire 控制面板冲突同一时间只能运行一个控制面板;测试会复用同一实例

最佳实践

  1. 使用 IAsyncLifetime - 确保正确地进行异步初始化和清理
  2. 通过集合共享固定装置 - 通过重复使用应用实例来缩短测试执行时间
  3. 动态发现端点 - 切勿硬编码 localhost:5000 或类似地址
  4. 等待健康检查 - 不要假设服务会立即就绪
  5. 使用真实依赖项进行测试 - Aspire 让使用真实的 SQL、Redis 等变得轻松
  6. 清理资源 - 始终正确实现 DisposeAsync
  7. 使用有意义的测试数据 - 使用真实的测试数据为数据库填充初始数据
  8. 测试故障场景 - 验证错误处理和弹性
  9. 保持测试隔离 - 每项测试都应独立,且不依赖执行顺序
  10. 监控测试执行时间 - 如果测试速度较慢,可考虑并行化

请参阅 ci-and-tooling.md,了解 GitHub Actions 设置、自定义资源等待器以及 Aspire CLI/MCP 集成。


调试技巧

  1. 运行 Aspire Dashboard - 测试失败时,请检查 http://localhost:15888 上的仪表板
  2. 将 Aspire CLI 与 MCP 配合使用 - 让 AI 助手查询实际应用状态
  3. 启用详细日志记录 - 设置 ASPIRE_ALLOW_UNSECURED_TRANSPORT=true 以获取更详细的输出
  4. 检查容器日志 - 使用 docker logs 检查容器输出
  5. 在固定装置中使用断点 - 调试固定装置初始化,以发现启动问题
  6. 验证资源名称 - 确保 AppHost 与测试中的资源名称一致

评论

支持 Markdown