共用方式為


撰寫您的第一個 .NET.NET Aspire 測試

在本文中,您將瞭解如何建立測試專案、撰寫測試,以及針對您的 .NET.NET Aspire 解決方案執行測試專案。 本文中的測試不是單元測試,而是功能或整合測試。 .NET .NET Aspire 包含數種 測試專案範本的變化, 可用來測試 .NET.NET Aspire 資源相依性及其通訊。 測試專案範本適用於 MSTest、NUnit 和 xUnit 測試架構,並包含可用來作為測試起點的範例測試。

.NET .NET Aspire 測試項目樣板依賴於 📦Aspire.Hosting.Testing NuGet 套件。 此套件會公開 DistributedApplicationTestingBuilder 類別,用來為分散式應用程式建立測試主機。 分散式應用程式測試產生器依賴 DistributedApplication 類別來建立和啟動 應用程式主機

建立測試專案

建立 .NET.NET Aspire 測試專案最簡單的方式是使用測試項目範本。 如果您要啟動新的 .NET.NET Aspire 專案,而且想要包含測試專案,Visual Studio 工具支援該選項。 如果您要將測試專案新增至現有的 .NET.NET Aspire 專案,您可以使用 dotnet new 命令來建立測試專案:

dotnet new aspire-xunit
dotnet new aspire-mstest
dotnet new aspire-nunit

如需詳細資訊,請參閱 .NET CLI dotnet new 命令檔。

探索測試專案

下列範例測試專案已建立為 .NET.NET Aspire 入門應用程式 範本的一部分。 如果您不熟悉,請參閱 快速入門:建置您的第一個 .NET.NET Aspire 專案。 .NET .NET Aspire 測試專案會在目標應用程式主機上建立專案參考的相依關係。 請考慮樣本專案:

<Project Sdk="Microsoft.NET.Sdk">

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


  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.Testing" Version="9.0.0" />
    <PackageReference Include="coverlet.collector" Version="6.0.2" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
    <PackageReference Include="xunit" Version="2.9.2" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\AspireApp.AppHost\AspireApp.AppHost.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Using Include="System.Net" />
    <Using Include="Microsoft.Extensions.DependencyInjection" />
    <Using Include="Aspire.Hosting.ApplicationModel" />
    <Using Include="Aspire.Hosting.Testing" />
    <Using Include="Xunit" />
  </ItemGroup>

</Project>
<Project Sdk="Microsoft.NET.Sdk">

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

  <PropertyGroup>
    <EnableMSTestRunner>true</EnableMSTestRunner>
    <OutputType>Exe</OutputType>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.Testing" Version="9.0.0" />
    <PackageReference Include="MSTest" Version="3.6.4" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\AspireApp.AppHost\AspireApp.AppHost.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Using Include="System.Net" />
    <Using Include="Microsoft.Extensions.DependencyInjection" />
    <Using Include="Aspire.Hosting.ApplicationModel" />
    <Using Include="Aspire.Hosting.Testing" />
    <Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
  </ItemGroup>

</Project>
<Project Sdk="Microsoft.NET.Sdk">

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


  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.Testing" Version="9.0.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
    <PackageReference Include="NUnit" Version="4.3.0" />
    <PackageReference Include="NUnit.Analyzers" Version="4.4.0" />
    <PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\AspireApp.AppHost\AspireApp.AppHost.csproj" />
  </ItemGroup>

  <ItemGroup>
    <Using Include="System.Net" />
    <Using Include="Microsoft.Extensions.DependencyInjection" />
    <Using Include="Aspire.Hosting.ApplicationModel" />
    <Using Include="Aspire.Hosting.Testing" />
    <Using Include="NUnit.Framework" />
  </ItemGroup>

</Project>

上述項目檔相當標準。 有一個 PackageReference📦Aspire的 .Hosting.Testing NuGet 套件,其中包含撰寫 .NET.NET Aspire 項目測試所需的類型。

範本測試專案包含一個 IntegrationTest1 類別和單一測試。 測試會驗證下列案例:

  • 已成功建立並啟動應用程式主機。
  • webfrontend 資源可供使用並正常運行。
  • 您可以對 webfrontend 資源提出 HTTP 要求,並傳回成功的回應 (HTTP 200 OK)。

請考慮下列測試類別:

namespace AspireApp.Tests;

public class IntegrationTest1
{
    [Fact]
    public async Task GetWebResourceRootReturnsOkStatusCode()
    {
        // Arrange
        var appHost = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

        appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
        {
            clientBuilder.AddStandardResilienceHandler();
        });

        // To output logs to the xUnit.net ITestOutputHelper, 
        // consider adding a package from https://www.nuget.org/packages?q=xunit+logging

        await using var app = await appHost.BuildAsync();

        var resourceNotificationService = app.Services
            .GetRequiredService<ResourceNotificationService>();

        await app.StartAsync();

        // Act
        var httpClient = app.CreateHttpClient("webfrontend");

        await resourceNotificationService.WaitForResourceAsync(
            "webfrontend",
            KnownResourceStates.Running
            )
            .WaitAsync(TimeSpan.FromSeconds(30));

        var response = await httpClient.GetAsync("/");

        // Assert
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }
}
namespace AspireApp.Tests;

[TestClass]
public class IntegrationTest1
{
    [TestMethod]
    public async Task GetWebResourceRootReturnsOkStatusCode()
    {
        // Arrange
        var appHost = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

        appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
        {
            clientBuilder.AddStandardResilienceHandler();
        });

        await using var app = await appHost.BuildAsync();

        var resourceNotificationService = app.Services
            .GetRequiredService<ResourceNotificationService>();

        await app.StartAsync();

        // Act
        var httpClient = app.CreateHttpClient("webfrontend");

        await resourceNotificationService.WaitForResourceAsync(
                "webfrontend",
                KnownResourceStates.Running
            )
            .WaitAsync(TimeSpan.FromSeconds(30));
        
        var response = await httpClient.GetAsync("/");

        // Assert
        Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
    }
}
namespace AspireApp.Tests;

public class IntegrationTest1
{
    [Test]
    public async Task GetWebResourceRootReturnsOkStatusCode()
    {
        // Arrange
        var appHost = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

        appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
        {
            clientBuilder.AddStandardResilienceHandler();
        });

        await using var app = await appHost.BuildAsync();

        var resourceNotificationService = app.Services
            .GetRequiredService<ResourceNotificationService>();

        await app.StartAsync();

        // Act
        var httpClient = app.CreateHttpClient("webfrontend");

        await resourceNotificationService.WaitForResourceAsync(
                "webfrontend",
                KnownResourceStates.Running
            )
            .WaitAsync(TimeSpan.FromSeconds(30));
        
        var response = await httpClient.GetAsync("/");

        // Assert
        Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
    }
}

上述程式代碼:

測試資源環境變數

若要進一步測試資源及其在 .NET.NET Aspire 解決方案中的表示相依性,您可以判斷是否正確地插入環境變數。 下列範例示範如何測試 webfrontend 資源是否有解析為 apiservice 資源的 HTTPS 環境變數:

using Aspire.Hosting;

namespace AspireApp.Tests;

public class EnvVarTests
{
    [Fact]
    public async Task WebResourceEnvVarsResolveToApiService()
    {
        // Arrange
        var appHost = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

        var frontend = (IResourceWithEnvironment)appHost.Resources
            .Single(static r => r.Name == "webfrontend");

        // Act
        var envVars = await frontend.GetEnvironmentVariableValuesAsync(
            DistributedApplicationOperation.Publish);

        // Assert
        Assert.Contains(envVars, static (kvp) =>
        {
            var (key, value) = kvp;

            return key is "services__apiservice__https__0"
                && value is "{apiservice.bindings.https.url}";
        });
    }
}
using Aspire.Hosting;

namespace AspireApp.Tests;

[TestClass]
public class EnvVarTests
{
    [TestMethod]
    public async Task WebResourceEnvVarsResolveToApiService()
    {
        // Arrange
        var appHost = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

        var frontend = (IResourceWithEnvironment)appHost.Resources
            .Single(static r => r.Name == "webfrontend");

        // Act
        var envVars = await frontend.GetEnvironmentVariableValuesAsync(
            DistributedApplicationOperation.Publish);

        // Assert
        CollectionAssert.Contains(envVars,
            new KeyValuePair<string, string>(
                key: "services__apiservice__https__0",
                value: "{apiservice.bindings.https.url}"));
    }
}
using Aspire.Hosting;

namespace AspireApp.Tests;

public class EnvVarTests
{
    [Test]
    public async Task WebResourceEnvVarsResolveToApiService()
    {
        // Arrange
        var appHost = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.AspireApp_AppHost>();

        var frontend = (IResourceWithEnvironment)appHost.Resources
            .Single(static r => r.Name == "webfrontend");

        // Act
        var envVars = await frontend.GetEnvironmentVariableValuesAsync(
            DistributedApplicationOperation.Publish);

        // Assert
        Assert.That(envVars, Does.Contain(
            new KeyValuePair<string, string>(
                key: "services__apiservice__https__0",
                value: "{apiservice.bindings.https.url}")));
    }
}

上述程式代碼:

總結

.NET Aspire 測試專案範本可讓您更輕鬆地建立 .NET Aspire 解決方案的測試專案。 範本專案包含可用來作為測試起點的範例測試。 DistributedApplicationTestingBuilder 遵循 ASP.NET Core中 WebApplicationFactory<TEntryPoint> 的熟悉模式。 它可讓您為分散式應用程式建立測試主機,並針對它執行測試。

最後,使用 DistributedApplicationTestingBuilder 預設會將所有資源記錄重新導向至 DistributedApplication。 資源記錄的重新導向使您能夠在您希望驗證資源是否正確記錄的情境下,達到目的。

另請參閱