使用 .NET Aspire 创建测试

已完成

测试是开发高质量软件的重要组成部分。 测试可帮助你查找和修复 bug、提高性能,并确保代码满足了用户的要求和期望。 测试还可以帮助你自动执行部署过程,并防止将来出现问题。 .NET Aspire 提供工具和库来简化分布式应用程序的开发、测试和部署。

在本单元中,你将了解如何使用适用于 .NET 的常用测试框架 xUnit 来测试 .NET Aspire 项目。 了解如何创建不同类型的测试,例如集成测试和功能测试,以及如何使用 .NET Aspire CLI 或 Visual Studio 运行它们。

创建测试项目

创建 .NET Aspire 测试项目的最简单方法是使用测试项目模板。 可以使用 dotnet new 命令创建标准类库项目,然后添加对 .NET Aspire 测试库和 xUnit 包的引用。

dotnet new aspire-xunit

浏览测试项目

以下示例测试项目是 .NET Aspire Starter 应用程序模板的一部分创建的。 如果不熟悉它,请参阅 快速入门:生成第一个 .NET Aspire 项目。 .NET Aspire 测试项目依赖于目标应用主机的项目来引用依赖项。 请考虑模板项目:

<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="Aspire.Hosting.Testing" Version="8.1.0" />
    <PackageReference Include="coverlet.collector" Version="6.0.2" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.0" />
    <PackageReference Include="xunit" Version="2.9.0" />
    <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>

上述项目文件相当标准。 有一个 PackageReference 指向 Aspire.Hosting.Testing NuGet 包,其中包括为 .NET Aspire 项目编写测试所需的类型。

模板测试项目包括具有单个测试的 WebTests 类。 该测试会验证以下方案:

  • 已成功创建并启动应用主机。
  • webfrontend 资源可用并运行。
  • 可以向 webfrontend 资源发出 HTTP 请求,并会返回成功的响应 (HTTP 200 OK)。

请考虑以下测试类:

namespace AspireApp.Tests;

public class WebTests
{
    [Fact]
    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.Equal(HttpStatusCode.OK, response.StatusCode);
    }
}

前面的代码:

  • 依赖于 DistributedApplicationTestingBuilder 以异步创建应用主机。
    • appHost 是表示应用主机的 IDistributedApplicationTestingBuilder 的实例。
    • appHost 实例使用标准 HTTP 复原处理程序配置了其服务集合。 有关详细信息,请参阅生成可复原 HTTP 应用:关键开发模式
  • appHost 会调用 BuildAsync 方法,该方法会将 DistributedApplication 实例作为 app 返回。
  • 通过调用 app.CreateHttpClientwebfrontend 资源创建 HttpClient
  • resourceNotificationService 用于等待 webfrontend 资源可用并运行。
  • webfrontend 资源的根目录发出简单的 HTTP GET 请求。
  • 测试会断言响应状态代码 OK