那些年用过的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 写在最后
平时要养成编写单元测试的好习惯。