mcpField
A
aspire-integration-testing

aspire-integration-testing

github.com/aarononthewebテスト・品質1.2k510 回インストール今日更新
リポジトリ

aspire-integration-testing について

.NET Aspire を使う開発者向けに、ASP.NET Core アプリや分散サービスの xUnit 統合テストを解説するスキルです。実際のインフラ、動的なエンドポイント検出、ヘルスチェックを使うテスト方法を扱います。

主な機能

  1. 01Aspire によるテストサービスの起動
  2. 02IAsyncLifetime によるフィクスチャ管理
  3. 03サービスエンドポイントの動的検出
  4. 04実データベースとコンテナーインフラの利用
  5. 05Playwright とメッセージキューのテスト

活用シーン

  1. 01ASP.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、メッセージキュー)を使用してテストする
  • Aspire がオーケストレーションするサービスと Playwright の UI テストを組み合わせる
  • 適切なサービス検出とネットワークを使用してマイクロサービスをテストする

参照ファイル

  • 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 つだけ実行できます。テストでは同じインスタンスを再利用します

ベストプラクティス

  1. IAsyncLifetime を使用する - 非同期の初期化とクリーンアップを適切に行えます
  2. コレクションでフィクスチャを共有する - アプリのインスタンスを再利用してテストの実行時間を短縮できます
  3. エンドポイントを動的に検出する - localhost:5000 などをハードコーディングしないでください
  4. ヘルスチェックを待つ - サービスがすぐに準備完了になると想定しないでください
  5. 実際の依存関係を使ってテストする - Aspire を使えば、実際の SQL、Redis などを簡単に利用できます
  6. リソースをクリーンアップする - DisposeAsync を必ず適切に実装してください
  7. 意味のあるテストデータを使う - 現実的なテストデータをデータベースにシードしてください
  8. 失敗するシナリオをテストする - エラー処理と回復性を検証してください
  9. テストを分離する - 各テストは独立し、実行順序に依存しないようにしてください
  10. テストの実行時間を監視する - テストが遅い場合は、並列化を検討してください

GitHub Actions のセットアップ、カスタムリソース待機処理、Aspire CLI/MCP 統合については、ci-and-tooling.md を参照してください。


デバッグのヒント

  1. Aspire Dashboard を実行する - テストが失敗したら、http://localhost:15888 のダッシュボードを確認してください
  2. MCP で Aspire CLI を使う - AI アシスタントに実際のアプリケーション状態を照会させます
  3. 詳細なログを有効にする - より詳細な出力を得るには、ASPIRE_ALLOW_UNSECURED_TRANSPORT=true を設定してください
  4. コンテナーのログを確認する - docker logs を使ってコンテナーの出力を調べてください
  5. フィクスチャにブレークポイントを設定する - フィクスチャの初期化をデバッグして、起動時の問題を特定してください
  6. リソース名を確認する - AppHost とテストでリソース名が一致していることを確認してください

コメント