Asp-Net-Core学习笔记:单元测试和集成测试
我在使用 AspNetCore 的这段时间内,看了很多开源项目和博客,发现各种 .Net 体系的新技术很多人都有关注和使用,但却很少有人关注测试。 测试是软件生命周期中的一个非常重要的阶段,对于保证软件的可靠性具有极其重要的意义。在应用程序的开发过程中,为了确保它的功能与预期一致,必须对其进行测试。这样做不仅能够确保功能正确执行,同时能够帮助开发人员尽早地发现并改正系统中所存在的缺陷(Bug),
目录13 个章节
前言
我在使用 AspNetCore 的这段时间内,看了很多开源项目和博客,发现各种 .Net 体系的新技术很多人都有关注和使用,但却很少有人关注测试。
测试是软件生命周期中的一个非常重要的阶段,对于保证软件的可靠性具有极其重要的意义。在应用程序的开发过程中,为了确保它的功能与预期一致,必须对其进行测试。这样做不仅能够确保功能正确执行,同时能够帮助开发人员尽早地发现并改正系统中所存在的缺陷(Bug),从而提高软件的可靠性。测试应该覆盖到软件的所有功能,全面、细致的测试会在很大程度上节省软件开发的成本;反之,不足的测试势必会使软件包含一些未发现的缺陷而投入运行,使用户承担软件缺陷所造成的危险。
从测试所涉及的层次上,分为单元测试、集成测试和系统测试。单元测试是指验证代码段(如方法或函数)功能的测试,通常由开发人员编写相应的测试方法,以验证代码执行后与预期结果是否一致;集成测试用于验证具有依赖关系的多个模块或组件是否能够正常工作;系统测试是对整个系统进行全面测试,以确认系统正常运行并符合需求。
本文主要记录一下单元测试和集成测试。
PS:本文只介绍简单的测试方法,抛砖引玉,更深入的使用可以参考官方文档,其中写得很清楚。
.Net 中的测试
.Net 的测试项目,主要有几种模板
- MSTest
- NUnit
- xUnit
本文选择 xUnit 作为测试项目模板。
单元测试
从测试所涉及的层次上,分为单元测试、集成测试和系统测试。单元测试是指验证代码段(如方法或函数)功能的测试,通常由开发人员编写相应的测试方法,以验证代码执行后与预期结果是否一致;集成测试用于验证具有依赖关系的多个模块或组件是否能够正常工作;系统测试是对整个系统进行全面测试,以确认系统正常运行并符合需求。
- Arrange:为测试进行准备操作,如设置测试数据、变量和环境等。
- Act:执行要测试的方法,如调用要测试的函数和方法。
- Assert:断言测试结果,验证被测试方法的输出是否与预期的结果一致。
最简单的例子
Controller 代码
[ApiController]
public class DemoController : ControllerBase {
[HttpGet("[action]")]
public ApiResponse Test() {
return ApiResponse.Ok("version=2.0");
}
}
单元测试代码
public class DemoTests {
private readonly DemoController _demoController;
public DemoTests() {
_demoController = new DemoController();
_demoController.ControllerContext = new ControllerContext {
HttpContext = new DefaultHttpContext()
};
}
[Fact]
public void Test_Test() {
var resp = _demoController.Test();
Assert.Equal("version=2.0", resp.Message);
}
}
带参数的 controller
实际开发中,Controller 会使用依赖注入,有很多参数
比如这个 controller ,用到了 EFCore 的 DbContext
public class StudentController : ControllerBase {
private readonly AppDbContext _dbCtx;
public StudentController(AppDbContext dbCtx) {
_dbCtx = dbCtx;
}
/// <summary>
/// 学生分数等级
/// </summary>
[HttpGet("[action]")]
public async Task<List<StudentGrades>> StudentScoreGrades() {
return await _dbCtx.StudentGrades.ToListAsync();
}
}
这时候在单元测试里,就得用 mock 对象框架 来实现依赖模拟
这里用的是 Moq 这个库,可以直接 nuget 安装
public class StudentTests {
private readonly StudentController _studentController;
public StudentTests() {
var mockOptions = new Mock<DbContextOptions<AppDbContext>>();
var mockDbContext = new Mock<AppDbContext>(mockOptions.Object);
_studentController = new StudentController(mockDbContext.Object) {
ControllerContext = new ControllerContext {
HttpContext = new DefaultHttpContext()
}
};
}
[Fact]
public async Task Test_StudentScoreGrades() {
var resp = await _studentController.StudentScoreGrades();
Assert.True(resp.Count > 0);
}
}
PS:实际使用的时候,这个 mock 还是挺麻烦的,所以这些接口还是用后面的集成测试更好。
集成测试
集成测试能够确保应用程序的组件正常工作,包括应用程序支持的基础结构,如数据库和文件系统等。ASP.NET Core提供了用于集成测试的组件,其中包含了用于测试的WebHost和内存测试服务器TestServer。与单元测试不同,这里所有的依赖都是模拟出来的,在集成测试中,应使用与生产环境中一样的真实组件,如数据库和第三方库等。
简单说,单元测试是把所有组件都模拟一遍,集成测试是在真实的系统上进行测试,比如 AspNetCore 开发的接口,集成测试直接使用 HTTP 请求,获取接口数据,然后检查这些返回数据是否符合条件。
开始前需要先安装依赖
dotnet add Microsoft.AspNetCore.Mvc.Testing
公开被测试项目的 Program/Startup 类
集成测试使用 WebApplicationFactory 来启动 AspNetCore 应用
所以需要在被测试的应用里做一点小修改,以便让测试项目可以访问到它的 Program 类
本文使用的被测试项目是基于 .Net6 的,修改它的 Program.cs ,添加以下代码
public partial class Program { }
使其 Program 类变成共有,让测试项目能够访问到。
官网文档上说还可以修改 .csproj ,添加配置
<ItemGroup>
<InternalsVisibleTo Include="MyTestProject" />
</ItemGroup>
但我试了好像没有效果,所以还是用第一种方法比较方便。
PS:如果是 .Net6 之前的项目,就把 Startup 类改成 public
例子
以刚才的 Student 接口为例
用 HTTP 请求这几个接口,然后判断返回的响应头里是否符合条件。
public class StudentTests : IClassFixture<WebApplicationFactory<Program>> {
private readonly WebApplicationFactory<Program> _factory;
public StudentTests(WebApplicationFactory<Program> factory) {
_factory = factory;
}
[Theory]
[InlineData("/api/v2/Student/StudentScoreGrades")]
[InlineData("/api/v2/Student/Height")]
[InlineData("/api/v2/Student/Weight")]
public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url) {
var client = _factory.CreateClient();
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
Assert.Equal("application/json; charset=utf-8; ver=2", response.Content.Headers.ContentType?.ToString());
}
}
更多示例
本文只介绍了 WebApi 的集成测试,实际开发可能还会对 MVC、Blazor 等项目进行测试
官方提供了一个实例项目: https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/test/integration-tests/IntegrationTestsSample
里面有很多集成测试的例子,可以参考一下。
运行测试
第一次测试需要先 Build 测试项目
本文使用的 IDE 是 Rider(VS 的话也是大同小异),其中提供了可视化的测试界面

之后写完新的测试直接点击旁边的绿色三角形,就可以单独运行这个新的测试。
参考资料
_EOF_
Asp-Net-Core学习笔记:单元测试和集成测试
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
Asp-Net-Core学习笔记:1.MVC入门篇
Asp.Net Core 学习 基于.Net Core 2.2版本的学习笔记。 常识 像Django那样自动检查代码更新,自动重载服务器(太方便了) dotnet watch run 托管设置 设置项目文件的AspNetCoreHostingModel属性。 PropertyGroup TargetFrameworknetcoreapp2.2/TargetFramework Asp
2022-02-16 · Asp-Net-Core学习笔记 · 约 1 分钟
Asp-Net-Core学习笔记:5.构建和部署
从上次开始学习Asp.Net Core以来,一直都是玩一玩,还没有什么机会用来实战,最近公司有个新的小项目,于是我用Asp.Net Core来尝尝新,结果也是非常OK,熟悉之后开发效率感觉和Django基本没差。 那么进入正题,本文简单说说Asp.Net Core应用的构建和部署。 构建 构建是使用build命令,不过一般我们都用vs或者rider之类的IDE,应该比较少会用到这个命令: dotn
2022-02-16 · Asp-Net-Core学习笔记 · 约 1 分钟
Asp-Net-Core学习笔记:身份认证入门
前言 过年前我又来更新了~ 我就说了最近不是在偷懒吧,其实这段时间还是有积累一些东西的,不过还没去整理…… 所以只能发以前没写完的一些笔记出来 就当做是温习一下啦 PS:之前说的红包封面我还没搞,得抓紧时间了 最近在准备搞一个我之前做的开源项目代码合集来做一期分享 两种常见的认证方式 先来看看两种常见的认证方式:基于token的认证和传统的session认证的区别。 session认证 我们知道,
2022-02-16 · Asp-Net-Core学习笔记 · 约 1 分钟
Asp-Net-Core学习笔记:部署,早知道,还是docker,以及一点碎碎念
前言 AspNetCore技术栈在我们团队里的使用也有一段时间了,之前的部署方式一直是本地编译之后上传可执行文件到服务器,使用supervisor来管理进程这种很原始的方式。 参考之前的文章: 对于小项目来说尚可,够用,但是存在几个问题: 每次更新花费的时间太长了,无论是Framework-Dependent还是Self-Contained,都要上传很大的文件~ 更新的时候需要在superviso
2022-02-16 · Asp-Net-Core学习笔记 · 约 1 分钟
讨论
共 0 条加载评论中…