Why doesn't Mockito mock static methods?

JavaMethodsStaticMockito

Java Problem Overview


I read a few threads here about static methods, and I think I understand the problems misuse/excessive use of static methods can cause. But I didn't really get to the bottom of why it is hard to mock static methods.

I know other mocking frameworks, like PowerMock, can do that but why can't Mockito?

I read this article, but the author seems to be religiously against the word static, maybe it's my poor understanding.

An easy explanation/link would be great.

Java Solutions


Solution 1 - Java

I think the reason may be that mock object libraries typically create mocks by dynamically creating classes at runtime (using cglib). This means they either implement an interface at runtime (that's what EasyMock does if I'm not mistaken), or they inherit from the class to mock (that's what Mockito does if I'm not mistaken). Both approaches do not work for static members, since you can't override them using inheritance.

The only way to mock statics is to modify a class' byte code at runtime, which I suppose is a little more involved than inheritance.

That's my guess at it, for what it's worth...

Solution 2 - Java

If you need to mock a static method, it is a strong indicator for a bad design. Usually, you mock the dependency of your class-under-test. If your class-under-test refers to a static method - like java.util.Math#sin for example - it means the class-under-test needs exactly this implementation (of accuracy vs. speed for example). If you want to abstract from a concrete sinus implementation you probably need an Interface (you see where this is going to)?

Solution 3 - Java

Mockito [3.4.0] can mock static methods!

  1. Replace mockito-core dependency with mockito-inline:3.4.0.

  2. Class with static method:

    class Buddy {
      static String name() {
        return "John";
      }
    }
    
  3. Use new method Mockito.mockStatic():

    @Test
    void lookMomICanMockStaticMethods() {
      assertThat(Buddy.name()).isEqualTo("John");
    
      try (MockedStatic<Buddy> theMock = Mockito.mockStatic(Buddy.class)) {
        theMock.when(Buddy::name).thenReturn("Rafael");
        assertThat(Buddy.name()).isEqualTo("Rafael");
      }
    
      assertThat(Buddy.name()).isEqualTo("John");
    }
    

    Mockito replaces the static method within the try block only.

Solution 4 - Java

As an addition to the Gerold Broser's answer, here an example of mocking a static method with arguments:

class Buddy {
  static String addHello(String name) {
    return "Hello " + name;
  }
}

...

@Test
void testMockStaticMethods() {
  assertThat(Buddy.addHello("John")).isEqualTo("Hello John");

  try (MockedStatic<Buddy> theMock = Mockito.mockStatic(Buddy.class)) {
    theMock.when(() -> Buddy.addHello("John")).thenReturn("Guten Tag John");
    assertThat(Buddy.addHello("John")).isEqualTo("Guten Tag John");
  }

  assertThat(Buddy.addHello("John")).isEqualTo("Hello John");
}

Solution 5 - Java

Mockito returns objects but static means "class level,not object level"So mockito will give null pointer exception for static.

Solution 6 - Java

I seriously do think that it is code smell if you need to mock static methods, too.

  • Static methods to access common functionality? -> Use a singleton instance and inject that
  • Third party code? -> Wrap it into your own interface/delegate (and if necessary make it a singleton, too)
The only time this seems overkill to me, is libs like Guava, but you shouldn't need to mock this kind anyway cause it's part of the logic... (stuff like Iterables.transform(..))
That way your own code stays clean, you can mock out all your dependencies in a clean way, and you have an anti corruption layer against external dependencies. I've seen PowerMock in practice and all the classes we needed it for were poorly designed. Also the integration of PowerMock at times caused serious problems
(e.g. https://code.google.com/p/powermock/issues/detail?id=355)

PS: Same holds for private methods, too. I don't think tests should know about the details of private methods. If a class is so complex that it tempts to mock out private methods, it's probably a sign to split up that class...

Solution 7 - Java

In some cases, static methods can be difficult to test, especially if they need to be mocked, which is why most mocking frameworks don't support them. I found http://www.lnbogen.com/2007/07/04/how-to-mock-static-class-or-static-member-for-testing/">this</a> blog post to be very useful in determining how to mock static methods and classes.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAbidiView Question on Stackoverflow
Solution 1 - JavaMatthiasView Answer on Stackoverflow
Solution 2 - JavaJanView Answer on Stackoverflow
Solution 3 - JavaGerold BroserView Answer on Stackoverflow
Solution 4 - JavaAlex ShesterovView Answer on Stackoverflow
Solution 5 - JavasalsingaView Answer on Stackoverflow
Solution 6 - Javapete83View Answer on Stackoverflow
Solution 7 - JavaTyler TreatView Answer on Stackoverflow