单元测试中的静态类/方法/属性,是否停止

2022-09-02 00:27:51

是否应该在单元测试开发环境中使用静态类/方法/属性,因为如果不引入同样不可测试的包装器,就无法对其进行测试?

另一种情况是,当在单元测试目标中使用静态成员时,无法模拟静态成员。因此,在测试单元测试目标时,必须测试静态成员。您希望在静态成员执行计算时将其隔离。


答案 1

测试静态方法与测试任何其他方法没有什么不同。在另一个测试模块中将静态方法作为依赖项会引发问题(正如已经提到的 - 你不能用免费工具模拟/存根它)。但是,如果静态方法本身经过单元测试,您可以简单地将其视为工作,可靠的组件

总的来说,在以下情况下,静态方法没有任何问题(例如,它不会破坏单元测试/ TDD):

  • 它是简单的输入输出方法(各种“计算给定的给定”)
  • 它是可靠的,按照我们的意思,它要么是由您测试的单元,要么是来自您认为可靠的第三方来源(例如。 可能被认为是可靠的 - 使用它不应该引起“注意,它是静态的!”警告;有人可能会认为微软做了它的工作)Math.Floor

静态方法何时会导致问题,应该避免?基本上只有当他们与无法控制(或模拟)的事情互动/做一些事情时:

  • 所有类型的文件系统、数据库、网络依赖关系
  • 从内部调用的其他(可能更复杂)静态方法
  • 几乎任何你的模拟框架无法定期处理的事情

编辑:关于静态方法何时会使单元测试变得困难的两个例子

1

public int ExtractSumFromReport(string reportPath)
{
     var reportFile = File.ReadAllText(reportPath);
     // ...
}

你如何处理?这显然会去文件系统检索文件内容,这在单元测试时是主要的禁忌。这是具有外部依赖关系的静态方法的示例。为了避免这种情况,您通常围绕文件系统API创建包装器,或者只是将其作为依赖项/委托注入。File.ReadAllText

2

public void SaveUser(User user)
{
    var session = SessionFactory.CreateSession();
    // ...
}

这又如何呢?会话是重要的依赖关系。当然,它可能会成为,但是如何强制返回模拟?我们不能。而且我们也不能创建易于识别的会话对象。ISessionSessionFactory

在上述情况下,最好完全避免使用静态方法。


答案 2

静态方法可以进行单元测试。它们不能被嘲笑(通常;有一些框架可以做到这一点,比如鼹鼠


推荐