简体   繁体   English

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

[英]How to mock static method without powermock

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?有没有其他选择?

(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

When you have static code 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).你转向 PowerMock(ito)。 Works fine.工作正常。
  • You turn to JMockit.你转向 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?"如果您正在测试自己编写的代码,您可能想退后一步问问自己:“为什么我编写的代码现在很难进行单元测试?”

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.一方面,这绝对是公平的。 static is one part of the Java language;静态是 Java 语言的一部分; so why not use a framework that allows you to deal with it?那么为什么不使用允许您处理它的框架呢?

But of course: you still have the static call in your production code then.但是当然:那时您的生产代码中仍然有静态调用。 Leading to tight coupling, and preventing polymorphism .导致紧耦合,防止多态

So: if you can get rid of the static call (even when just using the workaround suggested in the other answer) - all the better.所以:如果你能摆脱静态调用(即使只是使用另一个答案中建议的解决方法) - 那就更好了。 If not: Mockito can't help;如果不是:Mockito 无能为力; you need the magic of byte code manipulation resp.你需要字节码操作的魔力。 JVM agents. JVM 代理。

You can use Mockito (since version 3.4.0 ) to mock static methods.您可以使用Mockito (自3.4.0版起)来模拟静态方法。

Given a class Foo :给定一个类Foo

class Foo{
  static String method() {
    return "foo";
  }
}

This is the test:这是测试:

@Test
void testMethod() {
    assertEquals("foo", Foo.method());
    try (MockedStatic mocked = Mockito.mockStatic(Foo.class)) {
        mocked.when(Foo::method).thenReturn("bar");
        assertEquals("bar", Foo.method());
        mocked.verify(Foo::method);
    }
    assertEquals("foo", Foo.method());
}

This requires the dependency org.mockito:mockito-inline:3.4.0 or newer version.这需要依赖org.mockito:mockito-inline:3.4.0或更新版本。

I've had a lot of luck with doing something similar to what Maciej suggested in his answer above.我很幸运地做了一些类似于 Maciej 在上面的回答中建议的事情。 In Java8 I like to wrap those static methods with functional interfaces to make them more straightforward to inject or mock.在 Java8 中,我喜欢用函数式接口包装这些静态方法,使它们更容易注入或模拟。 For example:例如:

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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM