我试图想出一个应该使用严格模拟的场景。我想不出任何一个。
你什么时候使用严格的模拟?为什么?
答案 0 :(得分:5)
如果要验证是否已使用适当的参数调用了预期的方法,则使用正常(或松散)模拟。
严格模拟用于验证仅已调用预期方法而不是其他方法。把它们想象成一种负面的考验。
在大多数情况下,严格的嘲讽会使您的单位测试非常脆弱。即使您进行了少量的内部实施更改,测试也会失败。
但是,让我举一个可能有用的例子 - 测试一个要求,例如:
“获取缓存不应该命中数据库,如果它已包含数据”。
有很多方法可以通过松散的模拟来实现这一点,但是,简单地设置一个具有零预期函数调用的严格Mock<Database>
非常方便。对此数据库的任何调用都将引发异常并使测试失败。
您希望使用严格模拟的另一种情况是Adapter
或Wrapper
设计模式。在这种模式中,您没有执行太多的业务逻辑。测试这些类的主要部分是是否使用正确的参数(而不是其他参数)调用了基础函数。在这种情况下,严格的模拟效果相当不错。
答案 1 :(得分:0)
我有一个简单的约定:
当被测系统(SUT)将调用委托给底层模拟层而不真正修改或应用传递给自身的参数时,使用严格的模拟。
当SUT将业务逻辑应用于传递给自身的参数并将一些派生/修改的值传递给模拟层时,使用松散的模拟。
例如:假设我们有数据库提供者StudentDAL,它有两种方法:
数据访问界面如下所示:
Student GetStudentById(int id);
IList<Student> 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.
}