Java 如何在没有powermock的情况下模拟静态方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44967108/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to mock static method without powermock
提问by gati sahu
Is there any way we can mock the static util method while testing in JUnit?
在 JUnit 中进行测试时,有什么方法可以模拟静态 util 方法?
I know Powermock can mock static calls, but I don't want to use Powermock.
我知道 Powermock 可以模拟静态调用,但我不想使用 Powermock。
Are there any alternatives?
有没有其他选择?
回答by Maciej Kowalski
(I assume you can use Mockito though) Nothing dedicated comes to my mind but I tend to use the following strategy when it comes to situations like that:
(不过我假设你可以使用 Mockito)我没有想到专门的东西,但是当涉及到这样的情况时,我倾向于使用以下策略:
1)In the class under test, replace the static direct call with a call to a package level method that wraps the static call itself:
1)在被测类中,将静态直接调用替换为对封装静态调用本身的包级方法的调用:
public class ToBeTested{
public void myMethodToTest(){
...
String s = makeStaticWrappedCall();
...
}
String makeStaticWrappedCall(){
return Util.staticMethodCall();
}
}
2)Spy the class under test while testing and mock the wrapped package level method:
2)在测试的同时监视被测类并模拟包装的包级别方法:
public class ToBeTestedTest{
@Spy
ToBeTested tbTestedSpy = new ToBeTested();
@Before
public void init(){
MockitoAnnotations.initMocks(this);
}
@Test
public void myMethodToTestTest() throws Exception{
// Arrange
doReturn("Expected String").when(tbTestedSpy).makeStaticWrappedCall();
// Act
tbTestedSpy.myMethodToTest();
}
}
Here is an article I wrote on spying that includes similar case, if you need more insight: sourceartists.com/mockito-spying
这是我写的一篇关于间谍的文章,其中包括类似的案例,如果您需要更多的洞察力:sourceartists.com/mockito-spying
回答by GhostCat
When you have staticcode that gives you trouble in your unit tests; so that you feel you have to "mock it away", you have exactly these options:
当您的静态代码在单元测试中给您带来麻烦时;所以你觉得你必须“嘲笑它”,你有这些选择:
- You turn to PowerMock(ito). Works fine.
- You turn to JMockit. Works fine, too.
- If you are testing code you have written yourself, you might want to step back and ask yourself: "why did I write code that I now find hard to unit test?"
- 你转向 PowerMock(ito)。工作正常。
- 你转向 JMockit。工作正常,也是。
- 如果您正在测试自己编写的代码,您可能想退后一步问问自己:“为什么我编写的代码现在很难进行单元测试?”
In other words: if you want to use a mocking framework, you have to use one of those listed above. On the one side, that is absolutely fair. staticis one part of the Java language; so why not use a framework that allows you to deal with it?
换句话说:如果您想使用模拟框架,则必须使用上面列出的框架之一。一方面,这绝对是公平的。静态是 Java 语言的一部分;那么为什么不使用允许您处理它的框架呢?
But of course: you still have the staticcall in your production code then. Leading to tight coupling, and preventing polymorphism.
但是当然:那时您的生产代码中仍然有静态调用。导致紧耦合,防止多态。
So: if you can get rid of the staticcall (even when just using the workaround suggested in the other answer) - all the better. If not: Mockito can't help; you need the magic of byte code manipulation resp. JVM agents.
所以:如果你能摆脱静态调用(即使只是使用另一个答案中建议的解决方法) - 那就更好了。如果不是:Mockito 无能为力;你需要字节码操作的魔力。JVM 代理。
回答by Bryce
I've had a lot of luck with doing something similar to what Maciej suggested in his answer above. In Java8 I like to wrap those static methods with functional interfaces to make them more straightforward to inject or mock. For example:
我很幸运地做了一些类似于 Maciej 在上面的回答中建议的事情。在 Java8 中,我喜欢用函数式接口包装这些静态方法,使它们更容易注入或模拟。例如:
public class MyClass {
private MyStaticWrapper staticWrapper;
public MyClass(final MyStaticWrapper staticWrapper) {
this.staticWrapper = staticWrapper;
}
public void main() {
...
staticWrapper.doSomething();
...
}
}
public interface MyStaticWrapper {
default void doSomething() {
Util.annoyingUntestableStaticFunction();
}
}