有没有什么办法可以在JUnit中测试时模拟静态util方法?
我知道Powermock可以模拟静态调用,但我不想使用Powermock。
还有其他选择吗?
(我假设你可以使用Mockito)我没有任何专用的东西,但是当涉及到这样的情况时,我倾向于使用以下策略:
1)在被测试的类中,使用包装静态调用本身的包级别方法调用替换静态直接调用:
public class ToBeTested{
public void myMethodToTest(){
...
String s = makeStaticWrappedCall();
...
}
String makeStaticWrappedCall(){
return Util.staticMethodCall();
}
}
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();
}
}
如果你有静态代码,在你的单元测试中给你带来麻烦;所以你觉得你必须“嘲笑它”,你有这些选择:
换句话说:如果要使用模拟框架,则必须使用上面列出的其中一个。一方面,这绝对是公平的。 static是Java语言的一部分;那么为什么不使用一个允许你处理它的框架呢?
但当然:您的生产代码中仍然存在静态调用。导致紧密耦合,并防止多态性。
所以:如果你可以摆脱静态调用(即使只是使用其他答案中建议的解决方法) - 更好。如果不是:Mockito无能为力;你需要字节码操作的神奇之处。 JVM代理。
我做了很多运气,做了类似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();
}
}