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

Pin*_*ong 20 c# java tdd unit-testing

更新

应该在单元测试开发环境中使用静态类/方法/属性,因为如果不引入再次无法测试的包装器就无法测试它吗?

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

k.m*_*k.m 43

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

总体而言,在以下情况下使用静态方法没有任何错误(例如,它不会中断单元测试/ TDD):

  • 它很简单,输入输出法(各种"计算这个给出的")
  • 它是可靠的,我们的意思是它是由你单元测试的,或来自你认为可靠的第三方来源(例如Math.Floor可能被认为是可靠的 - 使用它不应该提出"注意,它是静态的!"警告;人们可能会认为微软做它的工作)

什么时候静态方法会引起问题而应该避免?基本上只有当他们与/ 做某事你无法控制(或模仿)时:

  • 各种文件系统,数据库,网络依赖
  • 从内部调用的其他(可能更复杂的)静态方法
  • 几乎任何你的模拟框架都无法按常规处理

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

1

public int ExtractSumFromReport(string reportPath)
{
     var reportFile = File.ReadAllText(reportPath);
     // ...
}
Run Code Online (Sandbox Code Playgroud)

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

2

public void SaveUser(User user)
{
    var session = SessionFactory.CreateSession();
    // ...
}
Run Code Online (Sandbox Code Playgroud)

那这个呢?会话是非平凡的依赖.当然,它可能会出现ISession,但是如何强制SessionFactory返回模拟呢?我们做不到.而且我们也无法创建易于确定的会话对象.

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

  • @Pingpong:你能扩展一下吗?`Math.Floor`执行计算 - 我们嘲笑它吗?不,因为我们知道`Math.Floor(2.5)`将返回2.当输入输出很容易确定**时,你不必模拟任何东西(或使用实例).整个*静态方法使得测试难度*来自它们提供非平凡依赖性或具有副作用的情况.看我的编辑. (2认同)