您现在的位置是:网站首页> 编程资料编程资料
ASP.NET Core项目使用xUnit进行单元测试_实用技巧_
2023-05-24
473人已围观
简介 ASP.NET Core项目使用xUnit进行单元测试_实用技巧_
一、前言
在以前的.NET Framework项目中,我们也写过一些单元测试的项目,而在ASP.NET Core 这种Web或者API应用程序中要做单元测试是很方便的。
这篇文章主要讲解如何使用xUnit对ASP.NET Core应用程序做单元测试。.NET Core中常用的测试工具还有NUnit和MSTest。
xUnit是一个测试框架,可以针对.net/.net core项目进行测试。测试项目需要引用被测试的项目,从而对其进行测试。测试项目同时需要引用xUnit库。测试编写好后,用Test Runner来运行测试。Test Runner可以读取测试代码,并且会知道我们所使用的测试框架,然后执行,并显示结果。目前可用的Test Runner包括vs自带的Test Explorer,或者dotnet core命令行,以及第三方工具,例如resharper等。
xUnit可以支持多种平台的测试:
- .NET Framework
- .NET Core
- .NET Standard
- UWP
- Xamarin
二、创建示例项目
为了使示例项目更加的贴近真实的项目开发,这里采用分层的方式创建一个示例项目,创建完成后的项目结构如下图所示:

下面讲解一下每层的作用,按照从上往下的顺序:
- TestDemo:从名字就可以看出来,这是一个单元测试的项目,针对控制器进行测试。
- UnitTest.Data:数据访问,封装与EntityFrameworkCore相关的操作。
- UnitTest.IRepository:泛型仓储接口,封装基础的增删改查。
- UnitTest.Model:实体层,定义项目中使用到的所有实体。
- UnitTest.Repository:泛型仓储接口实现层,实现接口里面定义的方法。
- UnitTestDemo:ASP.NET Core WebApi,提供API接口。
1、UnitTest.Model
实体层里面只有一个Student类:
using System; using System.Collections.Generic; using System.Text; namespace UnitTest.Model { public class Student { public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public string Gender { get; set; } } }2、UnitTest.Data
里面封装与EF Core有关的操作,首先需要引入Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.SqlServer、Microsoft.EntityFrameworkCore.Tools三个NuGet包,直接在管理NuGet程序包里面引入,这里不在讲述。
引入相关NuGet包以后,我们创建数据上下文类,该类继承自EF Core的DbContext,里面设置表名和一些属性:
using Microsoft.EntityFrameworkCore; using UnitTest.Model; namespace UnitTest.Data { /// /// 数据上下文类 /// public class AppDbContext : DbContext { /// /// 通过构造函数给父类构造传参 /// /// public AppDbContext(DbContextOptions options) : base(options) { } public DbSet Students { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().ToTable("T_Student"); modelBuilder.Entity().HasKey(p => p.ID); modelBuilder.Entity().Property(p => p.Name).HasMaxLength(32); // 添加种子数据 modelBuilder.Entity().HasData( new Student() { ID = 1, Name = "测试1", Age = 20, Gender = "男" }, new Student() { ID = 2, Name = "测试2", Age = 22, Gender = "女" }, new Student() { ID = 3, Name = "测试3", Age = 23, Gender = "男" }); base.OnModelCreating(modelBuilder); } } } 这里采用数据迁移的方式生成数据库,需要在API项目中引入Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.SqlServer、Microsoft.EntityFrameworkCore.Tools三个NuGet包。引入方式同上。
然后在API项目的appsettings.json文件里面添加数据库链接字符串:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", // 数据库连接字符串 "ConnectionString": { "DbConnection": "Initial Catalog=TestDb;User Id=sa;Password=1234;Data Source=.;Connection Timeout=10;" } }在JSON文件中添加完连接字符串以后,修改Startup类的ConfigureServices方法,在里面配置使用在json文件中添加的连接字符串:
// 添加数据库连接字符串 services.AddDbContext(options => { options.UseSqlServer(Configuration.GetSection("ConnectionString").GetSection("DbConnection").Value); });
这样就可以使用数据迁移的方式生成数据库了。
3、UnitTest.IRepository
该项目中使用泛型仓储,定义一个泛型仓储接口:
using System.Collections.Generic; using System.Threading.Tasks; namespace UnitTest.IRepository { public interface IRepository where T:class,new() { Task> GetList(); Task Add(T entity); Task Update(T entity); Task Delete(T entity); } }
然后在定义IStudentRepository接口继承自IRepository泛型接口:
using UnitTest.Model; namespace UnitTest.IRepository { public interface IStudentRepository: IRepository { } } 4、UnitTest.Repository
这里是实现上面定义的仓储接口:
using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnitTest.Data; using UnitTest.IRepository; using UnitTest.Model; namespace UnitTest.Repository { public class StudentRepository : IStudentRepository { private readonly AppDbContext _dbContext; /// /// 通过构造函数实现依赖注入 /// /// public StudentRepository(AppDbContext dbContext) { _dbContext = dbContext; } public async Task Add(Student entity) { _dbContext.Students.Add(entity); return await _dbContext.SaveChangesAsync(); } public async Task Delete(Student entity) { _dbContext.Students.Remove(entity); return await _dbContext.SaveChangesAsync(); } public async Task> GetList() { List list = new List(); list = await Task.Run>(() => { return _dbContext.Students.ToList(); }); return list; } public async Task Update(Student entity) { Student student = _dbContext.Students.Find(entity.ID); if (student != null) { student.Name = entity.Name; student.Age = entity.Age; student.Gender = entity.Gender; _dbContext.Entry(student).State = Microsoft.EntityFrameworkCore.EntityState.Modified; return await _dbContext.SaveChangesAsync(); } return 0; } } }
5、UnitTestDemo
先添加一个Value控制器,里面只有一个Get方法,而且没有任何的依赖关系,先进行最简单的测试:
using Microsoft.AspNetCore.Mvc; namespace UnitTestDemo.Controllers { [Route("api/[controller]")] [ApiController] public class ValueController : ControllerBase { [HttpGet("{id}")] public ActionResult Get(int id) { return $"Para is {id}"; } } } 6、TestDemo
我们在添加测试项目的时候,直接选择使用xUnit测试项目,如下图所示:

这样项目创建完成以后,就会自动添加xUnit的引用:
但要测试 ASP.NET Core 应用还需要添加两个 NuGet 包:
Install-Package Microsoft.AspNetCore.App Install-Package Microsoft.AspNetCore.TestHost
上面是使用命令的方式进行安装,也可以在管理NuGet程序包里面进行搜索,然后安装。
千万不要忘记还要引入要测试的项目。最后的项目引入是这样的:
netcoreapp3.1 false
都添加完以后,重新编译项目,保证生成没有错误。
三、编写单元测试
单元测试按照从上往下的顺序,一般分为三个阶段:
- Arrange:准备阶段。这个阶段做一些准备工作,例如创建对象实例,初始化数据等。
- Act:行为阶段。这个阶段是用准备好的数据去调用要测试的方法。
- Assert:断定阶段。这个阶段就是把调用目标方法的返回值和预期的值进行比较,如果和预期值一致则测试通过,否则测试失败。
我们在API项目中添加了一个Value控制器,我们以Get方法作为测试目标。一般一个单元测试方法就是一个测试用例。
我们在测试项目中添加一个ValueTest测试类,然后编写一个单元测试方法,这里是采用模拟HTTPClient发送Http请求的方式进行测试:
using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using System.Net; using System.Net.Http; using System.Threading.Tasks; using UnitTestDemo; using Xunit; namespace TestDemo { public class ValueTests { public HttpClient _client { get; } /// /// 构造方法 /// public ValueTests() { var server = new TestServer(WebHost.CreateDefaultBuilder() .UseStartup()); _client = server.CreateClient(); } [Fact] public async Task GetById_ShouldBe_Ok() { // 1、Arrange var id = 1; // 2、Act // 调用异步的Get方法 var response = await _client.GetAsync($"/api/value/{id}"); // 3、Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } } 我们在构造函数中,通过TestServer拿到一个HttpClient对象,用它来模拟Http请求。我们写了一个测试用例,完整演示了单元测试的Arrange、Act和Assert三个步骤。
1、运行单元测试
单元测试用例写好以后,打开“测试资源管理器”:
提示:
本文由神整理自网络,如有侵权请联系本站删除!
本站声明:
1、本站所有资源均来源于互联网,不保证100%完整、不提供任何技术支持;
2、本站所发布的文章以及附件仅限用于学习和研究目的;不得将用于商业或者非法用途;否则由此产生的法律后果,本站概不负责!
相关内容
- 基于ASP.NET实现验证码生成详解_实用技巧_
- ASP.NET Core使用AutoMapper实现实体映射_实用技巧_
- Entity Framework Core更新时间映射_实用技巧_
- Entity Framework Core表名映射_实用技巧_
- Entity Framework Core种子数据Data-Seeding_实用技巧_
- ASP.NET Core WebApi返回结果统一包装实践记录_实用技巧_
- asp.net core + jenkins 实现自动化发布功能_实用技巧_
- Visual Studio快捷键汇总_实用技巧_
- Bootstrap Blazor项目模板安装_实用技巧_
- Blazor组件的生命周期解析_实用技巧_
