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

时间:2012-05-17 09:25:54

标签: c# java unit-testing tdd

更新

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

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

5 个答案:

答案 0 :(得分:41)

测试静态方法与测试任何其他方法没有什么不同。在另一个测试模块中使用静态方法作为依赖会引发问题(因为它已被提及 - 你不能用免费工具模拟/存根)。但是如果静态方法本身是单元测试的,那么你可以简单地treat it as working, reliable component

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

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

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

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

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

<强> 1

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

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

<强> 2

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

这个怎么样?会话是非平凡的依赖关系。当然,它可能会ISession,但是如何强制SessionFactory返回模拟?我们做不到。我们也无法创建易于确定的会话对象。

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

答案 1 :(得分:3)

静态方法 CAN 进行单元测试。它们不能被嘲笑(通常;有一些框架可以像Moles那样做。

答案 2 :(得分:1)

您无法模拟静态方法/属性。因此,当classA使用classB的某个静态成员时,您无法单独测试classA

更新:我没有看到将一些静态类包装到对象中的任何问题。它不需要花费很多时间,但它允许您减少系统中的耦合。

答案 3 :(得分:0)

从技术上讲,你可以使用PowerMock来模拟Java中的静态方法,但如果你需要这样做,我会认真推荐重构你的代码。我认为静态方法应始终为private,并且仅在其定义的类中使用,以用于内部目的。我认为公开暴露静态方法为a code smell

答案 4 :(得分:0)

无论编程语言如何,我都会发现这种威胁,但由于我的日常生活与PHP有关,因此这里有很好的资源来处理PHP上的静态方法http://docs.mockery.io/en/latest/reference/public_static_properties.html