41
votes

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 there any alternatives?

4
You cannot mock static methods even if you use Mockito. - Abubakkar
Is there a reason why you do not want to use powermock? - Uwe Allner
Do you have to mock it? Is it your code and you can rewrite it so that there will be no statics? Static methods are death to testability - Arek
I noticed that your question is still "open" - as you didn't accept an answer. Please have a look and decide if you want to accept an answer. Or let me know if there is something I can do to enhance my input to make it accept worthy. Accepting helps future readers to determine if the problem is solved, and shows appreciation for the people who took the time answering you. Thanks! - GhostCat
@UweAllner, one reason for not using powermock is Code Coverage tool like JaCoCo may not consider code covered through powermock in code coverage report. - Dexter

4 Answers

35
votes

(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

10
votes

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.

5
votes

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.

2
votes

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