且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-11-16 22:27:34

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

Testing static method is no different than testing any other method. Having static method as a dependency inside another tested module raises problems (as it's been mentioned - you can't mock/stub it with free tools). But if the static method itself is unit tested you can simply treat it as working, reliable component.

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

Overall, there's nothing wrong (as in, it doesn't disrupt unit testing/TDD) with static methods when:

  • 很简单,输入输出法(各种计算这个给定那个")
  • 可靠,我们的意思是它要么经过您的单元测试,要么来自您认为可靠的第 3 方来源(例如,Math.Floor 可能被认为是可靠的- 使用它不应该引发注意,它是静态的!"警告;人们可能会认为微软已经完成了它的工作)
  • it is simple, input-output method (all kinds of "calculate this given that")
  • it is reliable, by what we mean it's either unit tested by you or comes from 3rd party source you consider reliable (eg. Math.Floor might be considered reliable - using it shouldn't raise "Look out, it's static!" warning; one might assume Microsoft does its job)

静态方法什么时候会导致问题,应该避免?基本上只有当他们与/做一些你无法控制的事情(或嘲笑)时:

When static methods will cause problems and should be avoided? Basically only when they interact with/do something you cannot control (or mock):

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

两个例子说明什么时候静态方法使单元测试变得困难

two examples on when static method will make unit testing hard

1

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

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

How do you deal with File.ReadAllText? This will obviously go to file system to retrieve file content, which is major no-no when unit testing. This is example of static method with external dependency. To avoid that, you usually create wrapper around file system api or simply inject it as dependency/delegate.

2

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

这个呢?会话是重要的 依赖项.当然,它可能是 ISession,但是如何强制 SessionFactory 返回模拟?我们不能.而且我们也不能创建易于确定的会话对象.

What about this? Session is non-trivial dependency. Sure, it might come as ISession, but how do force SessionFactory to return mock? We can't. And we can't create easy to detemine session object either.

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

In cases like above, it's best to avoid static methods altogether.