那些年用过的xUnit.net的简单用法
0x01 前言
单元测试,总是伴随着我们的开发过程,优劣自行google。当然呢,不排除有些公司是不做单元测试的,
但是呢,学多一点东西用来防身还是可以的。
0x02 简单的Demo
写个两数求和的方法,来进行简单的测试。
1 namespace Catcher.Lib 2 { 3 public class Method 4 { 5 public int Add(int num1,int num2) 6 { 7 return num1 + num2; 8 } 9 } 10 }
新建一个测试项目,添加xunit的相关引用以及我们测试方法所在的程序。
编写测试类MethodTest
1 using Xunit; 2 namespace Catcher.Lib.Test 3 { 4 public class MethodTest 5 { 6 Method method = new Method(); 7 [Fact] 8 public void add_two_integers_should_success() 9 { 10 int num1 = 3; 11 int num2 = 5; 12 int expected = 8; 13 int actual = method.Add(num1,num2); 14 Assert.Equal(expected,actual); 15 } 16 } 17 }
打开测试窗口,运行测试,看看测试结果
OK,测试通过。
注:要通过NuGet安装xunit.runner.visualstudio才可以看到测试窗口!
0x03 结合Moq来模拟数据访问层的操作
添加对应数据访问层的接口和类,以及模型(这里没有将模型单独抽出来。)
我在这里添加了一个IUserDAL接口和UserDAL类
IUserDAL具体如下
1 using Catcher.Lib.Model; 2 using System.Collections.Generic; 3 namespace Catcher.Lib 4 { 5 public interface IUserDAL 6 { 7 IList<UserInfo> GetAllUsers(); 8 bool AddUser(UserInfo user); 9 UserInfo GetUser(int id); 10 } 11 }
UserDAL具体如下
1 using Catcher.Lib.Model; 2 using System.Collections.Generic; 3 using System.Linq; 4 namespace Catcher.Lib.Implement 5 { 6 public class UserDAL : IUserDAL 7 { 8 public bool AddUser(UserInfo user) 9 { 10 using (DB db = new DB()) 11 { 12 db.UserInfoes.Add(user); 13 return db.SaveChanges() > 0; 14 } 15 } 16 public IList<UserInfo> GetAllUsers() 17 { 18 using (DB db = new DB()) 19 { 20 return db.UserInfoes.ToList(); 21 } 22 } 23 public UserInfo GetUser(int id) 24 { 25 using (DB db = new DB()) 26 { 27 return db.UserInfoes.Find(id); 28 } 29 } 30 } 31 }
都是些简单的操作,用到了EF,不做过多解释。
在测试项目添加一个UserDALTest的测试类。
1 using Catcher.Lib.Model; 2 using Moq; 3 using System; 4 using System.Collections.Generic; 5 using Xunit; 6 namespace Catcher.Lib.Test 7 { 8 public class UserDALTest 9 { 10 private List<UserInfo> _userList; 11 private UserInfo _user; 12 public UserDALTest() 13 { 14 //fake data 15 _userList = new List<UserInfo>(); 16 _userList.Add(new UserInfo { UserID = 1, UserName="catcher", UserIsActive=true }); 17 _userList.Add(new UserInfo { UserID = 2, UserName = "hawk", UserIsActive = false }); 18 _user = new UserInfo() { UserID=3, UserIsActive=true, UserName = "tom" }; 19 } 20 [Fact] 21 public void get_all_users_should_success() 22 { 23 //arrange 24 var fakeObject = new Mock<IUserDAL>(); 25 fakeObject.Setup(x=>x.GetAllUsers()).Returns(_userList); 26 //act 27 var res = fakeObject.Object.GetAllUsers(); 28 //assert 29 Assert.Equal(2,res.Count); 30 } 31 [Fact] 32 public void add_a_user_should_success() 33 { 34 var fakeObject = new Mock<IUserDAL>(); 35 36 fakeObject.Setup(x => x.AddUser(It.IsAny<UserInfo>())).Returns(true); 37 var res = fakeObject.Object.AddUser(_user); 38 Assert.Equal<bool>(true,res); 39 } 40 [Fact] 41 public void add_a_user_should_fail() 42 { 43 var fakeObject = new Mock<IUserDAL>(); 44 fakeObject.Setup(x => x.AddUser(It.IsAny<UserInfo>())).Returns(false); 45 var res = fakeObject.Object.AddUser(_user); 46 Assert.Equal<bool>(false, res); 47 } 48 [Fact] 49 public void get_a_user_by_valid_id_should_success() 50 { 51 var fakeObject = new Mock<IUserDAL>(); 52 fakeObject.Setup(x=>x.GetUser(It.IsAny<int>())).Returns(_user); 53 var res = fakeObject.Object.GetUser(3); 54 Assert.Equal(3,res.UserID); 55 Assert.Equal("tom",res.UserName); 56 Assert.Equal(true,res.UserIsActive); 57 } 58 [Fact] 59 public void get_a_user_by_invalid_id_should_throw_exception() 60 { 61 var fakeObject = new Mock<IUserDAL>(); 62 fakeObject.Setup(x => x.GetUser(It.IsAny<int>())).Throws(new NullReferenceException()); 63 Assert.Throws<NullReferenceException>(()=> fakeObject.Object.GetUser(4)); 64 } 65 } 66 }
这里对上面的UserDAL进行简单的说明,
在构造函数中制造了一个模拟的数据,
get_all_users_should_success 测试方法是测试GetAllUsers方法的。
add_a_user_should_success 测试方法是测试AddUser方法的,这个是添加成功的测试。
add_a_user_should_fail 测试方法是测试AddUser方法的,这个是添加失败的测试。
get_a_user_by_valid_id_should_success 测试方法是测试GetUser方法的,这个是查询成功的测试。
get_a_user_by_invalid_id_should_throw_exception 测试方法是测试GetUser方法的,这个是查询抛出异常的测试。
注:测试方法的命名应尽可能包含其操作与结果(个人看法)。
运行测试效果如下:
0x04 写在最后
平时要养成编写单元测试的好习惯。

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述