Unit testing 什么是严格的和非严格的模拟?
我已经开始使用moq进行模拟。有人能给我解释一下严格和非严格模拟的概念吗?如何在moq中使用它们 编辑:Unit testing 什么是严格的和非严格的模拟?,unit-testing,mocking,moq,Unit Testing,Mocking,Moq,我已经开始使用moq进行模拟。有人能给我解释一下严格和非严格模拟的概念吗?如何在moq中使用它们 编辑: 在哪种情况下,我们使用哪种类型的mock?我不确定moq的具体情况,但以下是Rhino中严格的mock是如何工作的。我声明我希望在我的对象foo上调用foo.Bar: foo.Expect(f => f.Bar()).Returns(5); 如果调用代码 foo.Bar(); 那么我很好,因为我的期望完全满足了 但是,如果调用代码为: foo.Quux(12); foo.Bar()
在哪种情况下,我们使用哪种类型的mock?我不确定moq的具体情况,但以下是Rhino中严格的mock是如何工作的。我声明我希望在我的对象
foo
上调用foo.Bar
:
foo.Expect(f => f.Bar()).Returns(5);
如果调用代码
foo.Bar();
那么我很好,因为我的期望完全满足了
但是,如果调用代码为:
foo.Quux(12);
foo.Bar();
然后我的期望失败了,因为我没有明确地期望调用foo.qux
总而言之,如果与预期不同,严格的模拟将立即失败。另一方面,非严格的mock(或存根)很乐意“忽略”对foo.qux
的调用,它应该为foo.qux
的返回类型T
返回default(T)
Rhino的创建者(并且更喜欢存根),因为您通常不希望在收到上述意外调用时测试失败。当您必须修复几十个依赖于原始行为的测试时,重构代码会变得更加困难。是否遇到过给定的/when/Then
- 给定上下文
- 当我表演一些活动时
- 然后就应该有结果了
- 非严格模拟:通常
- 严格模拟:最好不要
我通常会吃这样的东西
public class TestThis {
private final Collaborator1 collaborator1;
private final Collaborator2 collaborator2;
private final Collaborator2 collaborator3;
TestThis(Collaborator1 collaborator1, Collaborator2 collaborator2, Collaborator3 collaborator3) {
this.collaborator1 = collaborator1;
this.collaborator2 = collaborator2;
this.collaborator3 = collaborator3;
}
public Login login(String username) {
User user = collaborator1.getUser(username);
collaborator2.notify(user);
return collaborator3.login(user);
}
}
…我对3个合作者使用严格的模拟来测试登录名(用户名)。我不认为永远不应该使用严格的mock。我有一个简单的约定:
数据访问接口如下所示:
public Student GetStudentById(int id);
public IList<Student> GetStudents(int ageFilter, int classId);
public Student GetStudentById(int-id);
公共IList GetStudents(int ageFilter,int classId);
使用此DAL的实现如下所示:public Student FindStudent(int id)
{
//StudentDAL dependency injected
return StudentDAL.GetStudentById(id);
//Use strict mock to test this
}
public IList<Student> GetStudentsForClass(StudentListRequest studentListRequest)
{
//StudentDAL dependency injected
//age filter is derived from the request and then passed on to the underlying layer
int ageFilter = DateTime.Now.Year - studentListRequest.DateOfBirthFilter.Year;
return StudentDAL.GetStudents(ageFilter , studentListRequest.ClassId)
//Use loose mock and use verify api of MOQ to make sure that the age filter is correctly passed on.
}
公共学生查找学生(int id)
{
//学生依赖性注入
return StudentDAL.GetStudentById(id);
//使用strict mock来测试这一点
}
公共IList GetStudentsForClass(StudentListRequest StudentListRequest)
{
//学生依赖性注入
//年龄筛选器从请求派生,然后传递到底层
int ageFilter=DateTime.Now.Year-studentListRequest.DateOfBirthFilter.Year;
return StudentDAL.GetStudents(ageFilter,studentListRequest.ClassId)
//使用松散模拟并使用MOQ验证api,以确保正确传递老化过滤器。
}
您在哪里指定它是严格的模拟?@Sandbox:您可以在中指定严格或非严格。默认行为(当不指定MockBehavior
时)似乎不严格(他们称之为“松散”)。我认为最好在答案中包含Mark的注释;关于如何创建严格与非严格的解释,以及提到别名“loose”。我想知道严格与非严格是否与“严格单元测试”和“loose(blackbox)单元测试”之间的区别相同在“如何避免方法更改功能,然后由于所有单元测试仍然通过而没有任何测试验证此新功能的问题?”中介绍了@DanielLorenz如果要更改功能,请先编写一个失败的测试;这是TDD周期的核心部分,无论您使用的是哪种模拟。如果你指的是m