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

本文关键字:是否 方法 静态类 单元测试 属性 | 更新日期: 2023-09-27 18:34:22

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

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

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

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

总的来说,在

以下情况下,静态方法没有任何问题(例如,它不会中断单元测试/TDD(:

  • 这是简单的输入输出方法(各种"计算这个给定">(
  • 它是可靠的,
  • 我们的意思是它要么是由您测试的单元测试,要么来自您认为可靠的第三方来源(例如。 Math.Floor可能被认为是可靠的 - 使用它不应该引发"注意,它是静态的!">警告;人们可能会认为Microsoft完成了它的工作(

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

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

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

1

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

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

阿拉伯数字

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

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

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

静态方法可以进行单元测试。它们不能被嘲笑(一般来说;有一些框架可以像 Moles 一样做到这一点。

你不能模拟静态方法/属性。因此,当您的classA使用classB的某个静态成员时,您无法孤立地测试classA

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

从技术上讲,您可以使用PowerMock模拟Java中的静态方法,但是如果您需要这样做,我强烈建议重构您的代码。我认为静态方法应该始终private,并且仅在定义它们的类中使用,以用于内部目的。我认为公开的静态方法是一种代码异味。

无论编程语言

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