https://devblogs.microsoft.com/dotnet/getting-started-with-testing-and-dotnet-aspire/

自动化测试是软件开发的重要一环。它可以帮助我们尽早确认软件中的缺陷和防止回归问题。在本文中,我们将探讨如何在 .NET Aspire 中开始测试,支持我们进行跨分布式应用的测试场景。

测试分布式应用

分布式应用存在本质上的复杂性。你需要确保各种组件,例如数据库、缓存等等可用并且工作在正确的状态。然后,你的应用可能存在众多的服务需要一起进行测试。.NET Aspire 是非常棒的工具来帮助我们定义应用程序的环境,将众多的服务和资源连接在一起,进而比较容易地启动我们的环境。

对于端到端的测试也是这样,或者对于集成测试,我们需要确保数据库在期望的测试状态,避免其他的测试影响我们的测试,并且确保应用运行在正确的配置之下,这也是 .NET Aspire 可以提供帮助的地方。

谢天谢地,我们拥有了 .NET Aspire 的 Aspire.Hosting.Testing NuGet Package,它可以在这些方面帮助我们,让我们看一下我们可以如何使用它来编写测试用例。

入门

在开始的时候,我们将创建一个新的 .NET Aspire Starter App 项目,这将会创建一个新的使用了 AppHost 的 .NET Application,以及 Service Defaults, 和一个 API backend 和 一个 Blazor Web 前端项目。

首先确保你已经安装了 .NET Aspire workload

dotnet workload update
dotnet workload install aspire

然后,使用 aspire-starter 模板来创建新的项目。

dotnet new aspire-starter --name AspireWithTesting

然后,我们需要添加测试项目了,我们可以从 3 个测试框架中选择你希望的那个:

  • MSTest
  • xUnit
  • Nunit

例如,我们这里使用 MSTest。这可以通过使用 aspire-mstest 模板来完成。

dotnet new aspire-mstest --name AspireWithTesting.Tests
dotnet sln add AspireWithTesting.Tests

注意:在使用 aspire-starter 模板创建项目的时候,通过使用参数 --test-framework MSTest,你可以直接在新创建的项目中包含该测试项目。

在模板中已经引用了 Aspire-Hosting.Testing NuGet 包,以及选择的测试框架,在这里是 MSTest。所以,最后需要做的事情就是将测试项目添加到 AppHost 项目中。

dotnet add AspireWithTesting.Tests reference AspireWithTesting.AppHost

编写测试

你会发现这里已经提供了一个初始的测试文件,在上面描述中创建的测试项目中的 IntegrationTest1.cs。它提供了一个测试的示例,不过,我们还是从头编写一个,以便我们理解需要做的内容。创建一个新的名为 FrontEndTests.cs 的文件并试下下面的内容:

namespace AspireWithTesting.Tests;

[TestClass]
public class FrontEndTests
{
[TestMethod]
public async Task CanGetIndexPage()
{
var appHost =
await DistributedApplicationTestingBuilder
.CreateAsync<Projects.AspireWithTesting_AppHost>();
appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
{
clientBuilder.AddStandardResilienceHandler();
}); await using var app = await appHost.BuildAsync();
await app.StartAsync(); var resourceNotificationService =
app.Services.GetRequiredService<ResourceNotificationService>();
await resourceNotificationService
.WaitForResourceAsync("webfrontend", KnownResourceStates.Running)
.WaitAsync(TimeSpan.FromSeconds(30)); var httpClient = app.CreateHttpClient("webfrontend");
var response = await httpClient.GetAsync("/"); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
}

ResourceNotificationService 支持发布和订阅资源状态更改的服务。

好极了,测试已经写好了,让我们执行一下它。

dotnet test

如果所有的组件都在计划中执行,我们将应该看到如下的输出:

Test summary: total: 1, failed: 0, succeeded: 1, skipped: 0, duration: 0.9s

理解测试

让我分解上面的代码,理解在测试中发生了什么。

var appHost =
await DistributedApplicationTestingBuilder
.CreateAsync<Projects.AspireWithTesting_AppHost>();
appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
{
clientBuilder.AddStandardResilienceHandler();
}); await using var app = await appHost.BuildAsync();
await app.StartAsync();

测试的第一部分是利用在 AppHost 项目中定义的所有资源、服务和它们的关系,然后启动它们,如同在 AppHost 项目中执行 dotnet run 一样。但是在测试项目中,我们可以控制一些额外的方面。例如,我们可以注入 StandardResilienceHandlerHttpClient 中,这样测试中可以可以用来与 AppHost 中的服务交互。在 AppHost 配置之后,我们构建整个应用,准备开始执行测试。

var resourceNotificationService =
app.Services.GetRequiredService<ResourceNotificationService>();
await resourceNotificationService
.WaitForResourceAsync("webfrontend", KnownResourceStates.Running)
.WaitAsync(TimeSpan.FromSeconds(30));

因为 AppHost 将要启动多个不同的资源和服务,我们需要在基于它们执行我们的测试之前,确保它们可用。在这之后,如果 Web 应用没有正常启动,而我们试图访问它,我们就会得到一个错误。ResourceNotificationService 是用来帮助我们等待某个服务进入特定状态的服务。在我们的这个示例中,我们将等待 Webfrontend (这是配置在 AppHost 中的名称) 进入 Running 状态,我们使用 30s 的时间来等待。这个模式将需要对任何我们需要交互的服务使用,不管是直接还是间接。

var httpClient = app.CreateHttpClient("webfrontend");
var response = await httpClient.GetAsync("/"); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);

最后,我们可以从启动之后的应用中申请一个 HttpClient 的实例,提供希望访问的服务名称。这里将使用与以后的应用程序实际场景一样的服务发现机制,所以,我们不用担心服务的 URL 或者端口号。我们可以向服务发出请求,在我们的这个示例中,我们访问了 Web 前端的根目录 /,并检查我们是否得到一个 200 OK 的响应。来确认服务正确执行并如期望进行响应。

测试 API

测试 API 的方式非常类似于测试前端服务的方式,因为它返回的是数据,我们可以更进一步,可以根据返回的数据进行断言。

using System.Net.Http.Json;

namespace AspireWithTesting.Tests;

[TestClass]
public class ApiTests
{
[TestMethod]
public async Task CanGetWeatherForecast()
{
var appHost =
await DistributedApplicationTestingBuilder.CreateAsync<Projects.AspireWithTesting_AppHost>();
appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
{
clientBuilder.AddStandardResilienceHandler();
}); await using var app = await appHost.BuildAsync();
await app.StartAsync(); var resourceNotificationService =
app.Services.GetRequiredService<ResourceNotificationService>();
await resourceNotificationService
.WaitForResourceAsync("apiservice", KnownResourceStates.Running)
.WaitAsync(TimeSpan.FromSeconds(30)); var httpClient = app.CreateHttpClient("apiservice");
var response = await httpClient.GetAsync("/weatherforecast"); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); var forecasts = await response.Content.ReadFromJsonAsync<IEnumerable<WeatherForecast>>();
Assert.IsNotNull(forecasts);
Assert.AreEqual(5, forecasts.Count());
} record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary);
}

注意:由于这里涉及的 record 类型的 WeatherForecast 是在 API 项目中私有定义的,我们我们需要在测试项目中重新定义它,以便反序列化收到的 JSON 数据。

一旦我们断言 API 端点返回了期望的 200 OK 响应,我们可以进而反序列化收到的 JSON 响应为 WeatherForecast 对象的集合,并基于这些数据进一步断言。在我们的示例中,我们的 API 返回的是随机生成的数据,所以我们仅仅断言返回的 record 的数量,不过,如果我们的数据是来自于数据库中,那么,断言就可以根据期望的数据进行。

总结

在本文中,我们介绍了如何开始在 .NET Aspire 中进行测试。它使得我们可以处理分布式应用的测试场景。我们也看到了如何针对前端应用和 API 服务开发测试用例,确保它们运行并如期望进行响应。

Reference:

[.NET Blog] .NET Aspire 测试入门的更多相关文章

  1. Android渗透测试Android渗透测试入门教程大学霸

    Android渗透测试Android渗透测试入门教程大学霸 第1章  Android渗透测试 Android是一种基于Linux的自由及开放源代码的操作系统,主要用于移动设备,如智能手机.平板等.目前 ...

  2. IOS 客户端测试入门.pdf

    IOS 客户端测试入门  http://www.open-open.com/doc/view/42d1257bf67946f595e843bfdbdfeabf

  3. Python 3.6.3 官网 下载 安装 测试 入门教程 (windows)

    1. 官网下载 Python 3.6.3 访问 Python 官网 https://www.python.org/ 点击 Downloads => Python 3.6.3 下载 Python ...

  4. 转载:JMeter压力测试入门教程[图文]

    JMeter压力测试入门教程[图文] Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测试但后来扩展到其他测试领域. 它可 ...

  5. Jmeter压力测试入门操作

    Jmeter压力测试入门   1. 前言 Jmeter 是Apache组织开发的基于Java的压力测试工具,开源并且支持多个操作系统,是一款很好的HTTP测试工具.本篇文章主要的目的是帮助没有接触过J ...

  6. 渗透测试入门DVWA 教程1:环境搭建

    首先欢迎新萌入坑.哈哈.你可能抱着好奇心或者疑问.DVWA 是个啥? DVWA是一款渗透测试的演练系统,在圈子里是很出名的.如果你需要入门,并且找不到合适的靶机,那我就推荐你用DVWA. 我们通常将演 ...

  7. 安全性测试入门:DVWA系列研究(一):Brute Force暴力破解攻击和防御

    写在篇头: 随着国内的互联网产业日臻成熟,软件质量的要求越来越高,对测试团队和测试工程师提出了种种新的挑战. 传统的行业现象是90%的测试工程师被堆积在基本的功能.系统.黑盒测试,但是随着软件测试整体 ...

  8. 新萌渗透测试入门DVWA 教程1:环境搭建

    首先欢迎新萌入坑.哈哈.你可能抱着好奇心或者疑问.DVWA 是个啥? DVWA是一款渗透测试的演练系统,在圈子里是很出名的.如果你需要入门,并且找不到合适的靶机,那我就推荐你用DVWA. 我们通常将演 ...

  9. Android Monkey测试入门

    第一步:搭建环境:主要是安装和搭建java和sdk环境,说白了,对我们安卓开发来说,只要搭建好了Android开发环境,Monkey测试环境基本就是OK的了.可以参考:http://www.cnblo ...

  10. [大数据测试]ETL测试或数据仓库测试入门

    转载自: http://blog.csdn.net/zhusongziye/article/details/78633934 概述 在我们学习ETL测试之前,先了解下business intellig ...

随机推荐

  1. 利用 Page Visibility API 优化网页性能与用户体验

    在现代 Web 开发中,用户可能会频繁切换标签页,或让网页处于后台运行.为了避免不必要的资源浪费并提升用户体验,合理利用 Page Visibility API 可以在页面不可见时暂停或减少资源的消耗 ...

  2. 《Vue.js 设计与实现》读书笔记 - 第 4 章、响应系统的作用与实现

    第 4 章.响应系统的作用与实现 4.1 响应式数据与副作用 副作用函数就是会对外部造成影响的函数,比如修改了全局变量. 响应式:修改了某个值的时候,某个会读取该值的副作用函数能够自动重新执行. 4. ...

  3. BPF BTF 详解

    1. 介绍 BTF(BPF Type Format)是内嵌在BPF(Berkeley Packet Filter)程序中的数据结构描述信息.BPF原本是用于数据包过滤的编程语言,但随着eBPF(ext ...

  4. vue前端使用nexus配置npm私有仓库

    当我们运行前端项目的时候,常常在解决依赖的时候会加上一个参数npm install --registry=https://registry.npm.taobao.org将源指定为淘宝的源,以期让速度加 ...

  5. 新建 Blazor 项目 WebAssembly

  6. IHostedService(BackgroundService)的启动和停止顺序

    一句话总结: 按照Add顺序启动, 先启动, 后停止. Host 源代码 public async Task StartAsync(CancellationToken cancellationToke ...

  7. KubeSphere 社区双周报|2024.02.01-02.29

    KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...

  8. ajax下载二进制文件(导出Excel)

    var url = 'http://127.0.0.1'; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); // 也可以使用PO ...

  9. HTTP常用返回结果状态码

    摘编自<图解HTTP> HTTP状态码负责表示客户端 HTTP请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作.状态码的职责是当客户端向服务器端发送请求时,描述返回的请求 ...

  10. RMI,SOA,微服务

    什么是SOA SOA(Service-Oriented Architecture),中文全称:面向服务的架构. SOA提倡将不同应用程序的业务功能封装成"服务"并宿主起来,通常以接 ...