Search code examples
javaspring-bootunit-testingmockitopowermock

NotAMockException exception when trying to verify a static method with Powermockito


I use PowerMock to test a static method as mentioned its documentation.

As far as I see, there may be a bug, but I am not sure:

Static mocking broken for Mockito >= 2.26.1

...

I tried the workarounds mentioned on the following pages, however it does not fix the problem and some of them cannot be applicable as they are outdated.

NotAMockException when trying to verify a static method

verifyStatic get NotAMockExcption from mockito

However, I get "Argument passed to verify() is of type Class and is not a mock!" error. Here is the service method that I am testing and test method:

service:

// I want to test this method
 public CommandDTO create(EmployeeRequest request) {
    // ...

    log();
    return CommandDTO.builder().uuid(employee.getUuid()).build();
}


private void log() {
    LoggingUtils.info("Created...");
}

test:

@RunWith(PowerMockRunner.class)
@PrepareForTest(LoggingUtils.class)
public class EMployeeServiceImplTest {

    @Test
    public void unit_test() {

        // ...

        PowerMockito.mockStatic(LoggingUtils.class);

        employeeService.create(request);

        PowerMockito.verifyStatic(LoggingUtils.class); // throws error

        LoggingUtils.info(any());
    }
}

Here are libraries and versions:

pom.xml:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.4.6</version>
    <scope>test</scope>
</dependency>

Solution

  • Since you asked in another comment, here's a pattern I've used in the past to prevent the need for static mocking:

    Imagine we have a static method...

    public class SomeClass {
      public static String doSomething(int x) { ... }
    }
    

    Now imagine our code using it like this...

    public class MyClass {
      public void someMethod() {
        String xyz = SomeClass.doSomething(123);
        ...
      }
    }
    

    If we now needed to mock that SomeStaticClass.doSomething(123) call, we need static mocking.

    An alternative is a delegator:

    public class MyDelegator {
      public String doSomething(int x) { 
        return SomeClass.doSomething(x);
      } 
    }
    

    Now you can use that instead in your class:

    public class MyClass {
      private final MyDelegator myDelegator;
    
      public MyClass(MyDelegator myDelegator) { this.myDelegator = myDelegator; }
    
      public void someMethod() {
        String xyz = myDelegator.doSomething(123);
        ...
      }
    }
    

    And voila, you can simply mock the MyDelegator object instead of having to care that the original implementation was a static call.

    Of course, this doesn't solve the underlying code smell, but it can help you to work around it in cases where you cannot refactor the static code itself.