如何在没有powermock的情况下模拟静态方法

问题描述 投票:16回答:3

有没有什么办法可以在JUnit中测试时模拟静态util方法?

我知道Powermock可以模拟静态调用,但我不想使用Powermock。

还有其他选择吗?

java junit mockito powermock
3个回答
10
投票

(我假设你可以使用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();
    }
}

4
投票

如果你有静态代码,在你的单元测试中给你带来麻烦;所以你觉得你必须“嘲笑它”,你有这些选择:

  • 你转向PowerMock(ito)。工作良好。
  • 你转向JMockit。工作得很好。
  • 如果您正在测试自己编写的代码,那么您可能需要退后一步并问自己:“为什么我编写的代码现在很难进行单元测试?”

换句话说:如果要使用模拟框架,则必须使用上面列出的其中一个。一方面,这绝对是公平的。 static是Java语言的一部分;那么为什么不使用一个允许你处理它的框架呢?

但当然:您的生产代码中仍然存在静态调用。导致紧密耦合,并防止多态性。

所以:如果你可以摆脱静态调用(即使只是使用其他答案中建议的解决方法) - 更好。如果不是:Mockito无能为力;你需要字节码操作的神奇之处。 JVM代理。


0
投票

我做了很多运气,做了类似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();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.