新建一个类,用来测试。这个Create会使用仓储操作数据库。这里不希望实际操作数据库,以达到快速测试执行。
[Fact] public void Create_Ok() { IStudentRepositories studentRepositories = new StubStudentRepositories(); StudentService service = new StudentService(studentRepositories); var isCreateOk = service.Create(null); Assert.True(isCreateOk); } public class StubStudentRepositories : IStudentRepositories { public void Add(Student model) { } }图解:
每次做类似的操作都要手动建议StubStudentRepositories存根,着实麻烦。好在Mock框架(Moq)可以自动帮我们完成这个步骤。
例: [Fact] public void Create_Mock_Ok() { var studentRepositories = new Mock<IStudentRepositories>(); var notiy = new Mock<Notiy>(); StudentService service = new StudentService(studentRepositories.Object); var isCreateOk = service.Create(null); Assert.True(isCreateOk); }
相比上面的示例,是不是简化多了。起码代码看起来清晰了,可以更加注重测试逻辑。
下面接着来看另外的情况,并且已经通过了测试 public class Notiy { public bool Info(string messg) { //发送消息、邮件发送、短信发送。。。 //......... if (string.IsNullOrWhiteSpace(messg)) { return false; } return true; } } public class Notiy_Tests { [Fact] public void Info_Ok() { Notiy notiy = new Notiy(); var isNotiyOk = notiy.Info("消息发送成功"); Assert.True(isNotiyOk); } }
现在我们接着前面的Create方法加入消息发送逻辑。
public bool Create(Student student) { studentRepositories.Add(student); var isNotiyOk = notiy.Info("" + student.Name);//消息通知 //其他一些逻辑 return isNotiyOk; } [Fact] public void Create_Mock_Notiy_Ok() { var studentRepositories = new Mock<IStudentRepositories>(); var notiy = new Mock<Notiy>(); StudentService service = new StudentService(studentRepositories.Object, notiy.Object); var isCreateOk = service.Create(new Student()); Assert.True(isCreateOk); }而前面我们已经对Notiy进行过测试了,接下来我们不希望在对Notiy进行耗时操作。当然,我们可以通过上面的Mock框架来模拟。这次和上面不同,某些情况我们不需要或不想写对应的接口怎么来模拟?那就使用另外一种方式把要测试的方法virtual。
例:
测试如下
[Fact] public void Create_Mock_Notiy_Ok() { var studentRepositories = new Mock<IStudentRepositories>(); var notiy = new Mock<Notiy>(); notiy.Setup(f => f.Info(It.IsAny<string>())).Returns(true);//【1】 StudentService service = new StudentService(studentRepositories.Object, notiy.Object); var isCreateOk = service.CreateAndNotiy(new Student()); Assert.True(isCreateOk); }我们发现了标注【1】处的不同,这个代码的意思是,执行模拟的Info方法返回值为true。参数It.IsAny() 是任意字符串的意思。
当然你也可以对不同参数给不同的返回值:
有时候我们还需要对private方法进行测试
例:
private bool XXXInit() { return true; } [Fact] public void XXXInit_Ok() { var studentRepositories = new StudentService(); var obj = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject(studentRepositories); Assert.True((bool)obj.Invoke("XXXInit")); }如果方法有参数,接着Invoke后面传入即可。
好了,就说这么多吧。只能说测试的内容还真多,想要一篇文章说完是不可能的。但希望已经带你入门了。
附录xUnit(2.0) 断言 (来源)
Moq(4.7.10) It参数约束
相关资料
相关推荐
demo
posted @