【问题标题】:How to handle methods that cannot be mocked during unit testing如何处理单元测试期间无法模拟的方法
【发布时间】:2022-01-23 14:09:24
【问题描述】:

我想知道我们如何处理在编写单元测试时无法模拟的方法。

我们有一个名为 Student 的类,它有一组用于对学生数据进行操作的方法。我们还有一些用于进一步处理的扩展方法(在 C# 中)。现在我们的业务逻辑包括学生类方法和扩展方法的使用。

示例:

class Student
{
    // fields
    filter()
    check()
    ...
}
BusinessLogic()
{
   // get list of students
   return students.Where(filter()).someExtensionMethod().FirstOrDefault().check();
}

现在,如果我们想测试 BusinessLogic 方法,我们不能模拟方法 filter()、check() 和 someExtensionMethod()。如果我们采用常规方法,我们将设置测试数据,以便我们可以测试每个方法的输出并确保这些方法被调用。如果我们有这样的 2 或 3 个方法调用,这样做是可以的。但是我想知道如果有很多这样的方法调用并且方法涉及复杂的逻辑,这使得我们的测试数据设置更加复杂,该怎么办?

编辑: 在这里,我对 Student 类中定义的函数感兴趣。例如,我有功能可以检查学生的分数是否超过 33。就像 IsPass()。我将其称为 student.IsPass()。但问题是在实际项目中,此类方法的数量可能很大。而我们的业务逻辑可以是这些方法的组合

【问题讨论】:

  • 我认为第一个问题应该是:你到底想测试什么?
  • 我想测试上面例子中的 BusinessLogic 方法。但我真正的意思是,我们如何测试包含上述方法调用的方法。

标签: c# unit-testing mocking


【解决方案1】:

我会将负责在单独的类中检索学生数据的逻辑分开,例如“StudentRepository”。然后为这个类创建一个接口,并将其用作 BusinessLogic 中的依赖项。

public interface IStudentRepository
{
   IEnumerable<Student> GetStudents();
}

IStudentRepository 的实现取决于您的数据存储。

在 BusinessLogic 类中,您将有一个“IStudentRepository”依赖项:

public BusinessLogic(IStudentRepository studentRepository)
{
   // get list of students
   var students = studentRepository.GetStudents();

   // perform business logic on students

}

【讨论】:

  • 我对获取学生数据并不是特别感兴趣。在这里,我对 Student 类中定义的函数感兴趣。例如,我有功能可以检查学生的分数是否超过 33。就像 IsPass()。我将其称为 student.IsPass()。但问题是在实际项目中,此类方法的数量可能很大。而我们的业务逻辑可以是这些方法的组合。
  • 然后我将使用 'IsPass' 方法的代码提取到一个单独的类中,为这个类创建一个接口,例如“IStudentGradesChecker”然后使用对这个接口的依赖。如果您想为没有源代码的类添加功能,通常更推荐使用扩展方法(在这种情况下,您没有太多选择来向它们添加功能)。但在您的场景中并非如此。
  • 但是将方法提取到接口中是否明智,这是类本身的责任。我说的是类本身负责的方法。
  • 如果你想模拟这些方法的行为,即设置一个不使用“Pass”方法的真正实现,而是使用它的模拟行为的单元测试,例如总是返回true,那么你需要一个接口。但也许您不想真正模拟这些方法?但这就是你的问题所指的。
  • 是的,所以我的问题是如果有我们无法模拟的方法怎么办。有没有办法处理这种情况?
猜你喜欢
  • 2018-06-16
  • 1970-01-01
  • 2014-04-16
  • 1970-01-01
  • 2015-10-21
  • 1970-01-01
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
相关资源
最近更新 更多