为什么 Mockito 不模拟静态方法?
我在这里阅读了一些有关静态方法的线程,我想我理解误用/过度使用静态方法可能导致的问题。但我并没有真正弄清楚为什么很难模拟静态方法。
我知道其他模拟框架(例如 PowerMock)可以做到这一点,但为什么 Mockito 不能?
我阅读了这篇文章,但是作者似乎非常反对静态这个词,也许这是我的理解很差。
一个简单的解释/链接会很棒。
I read a few threads here about static methods, and I think I understand the problems misuse/excessive use of static methods can cause. But I didn't really get to the bottom of why it is hard to mock static methods.
I know other mocking frameworks, like PowerMock, can do that but why can't Mockito?
I read this article, but the author seems to be religiously against the word static
, maybe it's my poor understanding.
An easy explanation/link would be great.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我认为原因可能是模拟对象库通常通过在运行时动态创建类来创建模拟(使用cglib)。这意味着它们要么在运行时实现一个接口(如果我没记错的话,这就是 EasyMock 所做的),要么从类继承来进行模拟(如果我没有记错的话,这就是 Mockito 所做的)。这两种方法都不适用于静态成员,因为您无法使用继承来覆盖它们。
模拟静态的唯一方法是在运行时修改类的字节代码,我认为这比继承更复杂一些。
这就是我的猜测,因为它的价值......
I think the reason may be that mock object libraries typically create mocks by dynamically creating classes at runtime (using cglib). This means they either implement an interface at runtime (that's what EasyMock does if I'm not mistaken), or they inherit from the class to mock (that's what Mockito does if I'm not mistaken). Both approaches do not work for static members, since you can't override them using inheritance.
The only way to mock statics is to modify a class' byte code at runtime, which I suppose is a little more involved than inheritance.
That's my guess at it, for what it's worth...
如果您需要模拟静态方法,则这是一个糟糕设计的强烈指标。通常,您会模拟被测类的依赖关系。如果您的被测类引用静态方法(例如 java.util.Math#sin),则意味着被测类恰好需要此实现(例如,准确性与速度)。如果您想从具体的正弦实现中抽象出来,您可能需要一个接口(您知道这会去哪里)?
If you need to mock a static method, it is a strong indicator for a bad design. Usually, you mock the dependency of your class-under-test. If your class-under-test refers to a static method - like java.util.Math#sin for example - it means the class-under-test needs exactly this implementation (of accuracy vs. speed for example). If you want to abstract from a concrete sinus implementation you probably need an Interface (you see where this is going to)?
Mockito [3.4.0] 可以模拟静态方法!
替换
mockito-core
与mockito-inline:3.4.0< 的依赖关系/代码>.
具有静态方法的类:
使用新方法
Mockito.mockStatic()
:Mockito 仅替换
try
块中的静态方法。Mockito [3.4.0] can mock static methods!
Replace
mockito-core
dependency withmockito-inline:3.4.0
.Class with static method:
Use new method
Mockito.mockStatic()
:Mockito replaces the static method within the
try
block only.作为 Gerold Broser 的答案的补充,这里是一个使用参数模拟静态方法的示例:
As an addition to the Gerold Broser's answer, here an example of mocking a static method with arguments:
Mockito返回对象,但static意味着“类级别,而不是对象级别”,因此mockito会给static带来空指针异常。
Mockito returns objects but static means "class level,not object level"So mockito will give null pointer exception for static.
我认真地认为,如果您也需要模拟静态方法,那就是代码味道。
唯一一次对我来说似乎有点过分,是像 Guava 这样的库,但您无论如何都不应该需要模拟这种类型,因为它是逻辑的一部分...(像 Iterables.transform(..) 之类的东西)
这样您自己的代码就保持干净,您可以以干净的方式模拟所有依赖项,并且您拥有针对外部依赖项的反腐败层。
我在实践中见过 PowerMock,但我们需要它的所有类都设计得很糟糕。此外,PowerMock 的集成有时会导致严重问题
(例如 https ://code.google.com/p/powermock/issues/detail?id=355)
PS:私有方法也同样如此。我认为测试不应该了解私有方法的细节。如果一个类如此复杂以至于它试图模拟私有方法,那么这可能是拆分该类的标志......
I seriously do think that it is code smell if you need to mock static methods, too.
The only time this seems overkill to me, is libs like Guava, but you shouldn't need to mock this kind anyway cause it's part of the logic... (stuff like Iterables.transform(..))
That way your own code stays clean, you can mock out all your dependencies in a clean way, and you have an anti corruption layer against external dependencies.
I've seen PowerMock in practice and all the classes we needed it for were poorly designed. Also the integration of PowerMock at times caused serious problems
(e.g. https://code.google.com/p/powermock/issues/detail?id=355)
PS: Same holds for private methods, too. I don't think tests should know about the details of private methods. If a class is so complex that it tempts to mock out private methods, it's probably a sign to split up that class...
在某些情况下,静态方法可能很难测试,特别是当它们需要被模拟时,这就是为什么大多数模拟框架不支持它们的原因。我发现 这篇博客文章对于确定如何模拟静态方法和类非常有用。
In some cases, static methods can be difficult to test, especially if they need to be mocked, which is why most mocking frameworks don't support them. I found this blog post to be very useful in determining how to mock static methods and classes.