How to mock static method without powermock

前端 未结 4 1664
野趣味
野趣味 2020-12-09 01:53

Is there any way we can mock the static util method while testing in JUnit?

I know Powermock can mock static calls, but I don\'t want to use Powermock.

Are

相关标签:
4条回答
  • 2020-12-09 02:17

    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:

    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();
        }
    }
    
    0 讨论(0)
  • 2020-12-09 02:23

    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). 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?"

    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; 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; you need the magic of byte code manipulation resp. JVM agents.

    0 讨论(0)
  • 2020-12-09 02:29

    (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:

    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:

    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:

    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

    0 讨论(0)
  • 2020-12-09 02:43

    You can use Mockito (since version 3.4.0) to mock static methods.

    Given a class 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.

    0 讨论(0)
提交回复
热议问题