【问题标题】:When to use strict mocks?何时使用严格的模拟?
【发布时间】:2014-07-02 00:29:26
【问题描述】:

我正在尝试提出一个应该使用严格模拟的场景。我想不出来。

你什么时候使用严格的模拟,为什么?

【问题讨论】:

标签: unit-testing mocking tdd moq


【解决方案1】:

我有一个简单的约定:

当被测系统 (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.

}

【讨论】:

  • 我不同意 FindStudent(int id) 应该用严格的模拟来测试。根本不应该对 StudentDAL 进行检查。查看 Mark Seemann 的博客文章 - 我的问题下的链接。
【解决方案2】:

当您想要验证是否使用正确的参数调用了预期的方法时,可以使用普通(或松散)模拟。

严格的模拟用于验证调用了预期的方法,而没有调用其他方法。将它们视为一种负面测试。

在大多数情况下,严格的模拟会使您的单元测试非常脆弱。即使您对内部实现进行小的更改,测试也会开始失败。

但让我举个例子,它们可能有用 - 测试一个需求,例如:

“如果缓存中已包含数据,则获取缓存不应访问数据库”。

有一些方法可以通过松散的模拟来实现这一点,但相反,只需设置一个严格的 Mock&lt;Database&gt; 并期望函数调用为零就非常方便。对该数据库的任何调用都会引发异常并导致测试失败。


您想要使用严格模拟的另一种情况是AdapterWrapper 设计模式。在这种模式中,您不会执行太多业务逻辑。测试这些类的主要部分是是否使用正确的参数(而不是其他参数)调用了底层函数。在这种情况下,严格的模拟效果相当好。

【讨论】:

    猜你喜欢
    • 2021-09-07
    • 2017-06-17
    • 2011-03-09
    • 2014-08-29
    • 1970-01-01
    • 2013-10-08
    • 2011-12-21
    • 2017-11-19
    相关资源
    最近更新 更多