Search code examples
javakotlinmockingmockitopowermockito

I'm creating unit test for a static class and it has method call of another static method from same class? How to can mock that method call?


How can I create unit test for testAble() method and mock the behavior of something() method?

public class MyClass {
    public static String something() {
        return "Hello";
    }

    public static String testAble() {
        if (something().equals("Hello")) {
            return "Wow";
        }
        return "LoL";
    }
}

I was trying to do it using Mockito but I came to know that we can't mock static using Mockito.


Solution

  • Since Mockito version 3.4.0 it's possible to mock static methods when using mockito-inline dependency - see: Mockito docs or you can read more here.

    In your case it would look like this:

    @Test
    void notHelloTest() {
        try (var mocked = Mockito.mockStatic(MyClass.class, CALLS_REAL_METHODS)) {
            mocked.when(MyClass::something)
                  .thenReturn("not hello");
    
            var result = MyClass.testAble();
    
            assertEquals("LoL", result);
        }
    }
    
    @Test
    void helloTest() {
        try (var mocked = Mockito.mockStatic(MyClass.class, CALLS_REAL_METHODS)) {
            mocked.when(MyClass::something)
                  .thenReturn("Hello");
    
            var result = MyClass.testAble();
    
            assertEquals("Wow", result);
        }
    }
    

    Please note the CALLS_REAL_METHODS parameter (static import from org.mockito.Answers) passed to mockStatic method - it's required since we're testing the same class that we're mocking. Without it MyClass.testAble() returns null as we're not defining its behavior (and we want to test it, not mock it).

    I've created a GitHub repository reproducing your question, where I've also added the tests above - they both pass.

    Additional note: you could solve the problem by using non-static methods instead of static ones and injecting the instance of your class into another class (and inject a test double in tests). Dependency injection mechanisms make it easy for us.

    You may also want to read about the try-with-resources block - static mocking works only within the try block and the static mock is closed when the block ends.