为什么Mockito没有模拟静态方法?

我在这里阅读了一些关于静态方法的线程,我想我明白了误用/过度使用静态方法会导致的问题。 但我并没有真正了解为什么很难模拟静态方法。

我知道其他嘲弄框架,比如PowerMock,可以做到这一点,但为什么不能Mockito?

我读过这篇文章 ,但作者似乎虔诚地反对static这个词,也许这是我理解不足的原因。

一个简单的解释/链接将是伟大的。

我认为原因可能是模拟对象库通常通过在运行时动态创建类来创建模拟(使用cglib )。 这意味着他们要么在运行时实现一个接口(这就是EasyMock在没有弄错的情况下所做的事情),或者他们从类inheritance到mock(这就是Mockito如果我没有弄错的话)。 这两种方法都不适用于静态成员,因为您无法使用inheritance覆盖它们。

模拟静态的唯一方法是在运行时修改类的字节代码,我认为这比inheritance更复杂。

这是我对它的猜测,因为它的价值……

如果你需要模拟静态方法,它是一个糟糕设计的强大指标。 通常,您可以模拟被测试类的依赖关系。 如果你的被测试类是指一个静态方法 – 例如java.util.Math#sin–这意味着被测试类正好需要这个实现(例如精度与速度)。 如果你想从具体的正弦实现中抽象出来,你可能需要一个接口(你会看到它的去向)?

如果你需要模拟静态方法,我认真地认为它是代码味道。

  • 访问常用function的静态方法? – >使用单例实例并注入它
  • 第三方代码? – >将它包装到您自己的接口/委托中(如果需要,也可以将它作为单例)

这对我来说似乎有点过分了,就像Guava这样的库,但你不应该嘲笑这种类型,因为它是逻辑的一部分…(像Iterables.transform(..)这样的东西)
这样你自己的代码就会保持干净,你可以用干净的方式模拟所有的依赖项,并且你有一个针对外部依赖的反腐败层。 我在实践中看过PowerMock,我们需要的所有类都设计得很差。 此外,PowerMock的集成有时会引起严重的问题
(例如https://code.google.com/p/powermock/issues/detail?id=355 )

PS:同样适用于私人方法。 我认为测试不应该知道私有方法的细节。 如果一个类是如此复杂以至于它试图模仿私有方法,那么它可能是分裂该类的一个标志……

Mockito返回对象但静态意味着“类级别,而不是对象级别”因此mockito将为静态提供空指针exception。

在某些情况下,静态方法可能难以测试,特别是如果需要进行模拟,这就是大多数模拟框架不支持它们的原因。 我发现这篇博客文章在确定如何模拟静态方法和类时非常有用。