javajunitmockitopowermock

Error:org.mockito.exceptions.misusing.MissingMethodInvocationException


I am getting the below error while upgrading java to 17 and mockito to 3.7.7 and junit4 to junit 5 and also I am using these powermock dependencies.

'org.powermock:powermock-module-junit4:2.0.7', 'org.powermock:powermock-core:2.0.7', 'org.powermock:powermock-api-mockito2:2.0.7'

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.

    at app//com.expedia.risk.clm.web.exception.handler.RestExceptionMappingHandlerTest.shouldHandleMethodArgumentNotValid(RestExceptionMappingHandlerTest.java:118)
    at app//org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at app//org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at app//org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at app//org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at app//org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at app//org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:54)
    at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at app//org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at app//org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at app//org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at app//org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at app//org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:99)
    at app//org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:105)
    at app//org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:40)

My test case code is like this. Could someone please help how to resolve this.

    @Test
    public void shouldHandleMethodArgumentNotValid() {
        final Set<InputError> testInputErrors = Collections.singleton(new InputError("test", "test"));
        final String expectedMessage = String.format("Invalid input. Details: %s", testInputErrors.toString());
        final MethodArgumentNotValidException testException = mock(MethodArgumentNotValidException.class);
        final BindingResult testBindingResult = mock(BindingResult.class);
        final List<ObjectError> testErrors = Collections.singletonList(new ObjectError("test", "test"));
        when(testException.getBindingResult()).thenReturn(testBindingResult);
        when(testBindingResult.getAllErrors()).thenReturn(testErrors);

        final ResponseEntity<ClmErrorResponse> actualResponse = handler.handleMethodArgumentNotValid(testException);

        assertThat(actualResponse.getStatusCode(), is(HttpStatus.BAD_REQUEST));
        final ClmErrorResponse errorResponse = actualResponse.getBody();
        assertThat(errorResponse.getCode(), is("39071"));
        assertThat(errorResponse.getMessage(), is(expectedMessage));
        assertThat(errorResponse.getInputErrors(), is(testInputErrors));
        verify(testException).getBindingResult();
        verify(testBindingResult).getAllErrors();
        verifyNoMoreInteractions(testBindingResult);
    }

try upgrading and degrading the versions of mockito and powermock.


Solution

  • You're trying to mock a method that is final:

    Also, this error might show up because:

    1. you stub either of: final/private/equals()/hashCode() methods.

    and BindException.getBindingResult() is:

    public class BindException .. {
    
        ...
    
        public final BindingResult getBindingResult() {
            return this.bindingResult;
        }
    }
    

    It's hard to tell without seeing your code, but you're probably not using PowerMock correctly. This answer gives an example on how to mock a final method: Can Powermockito mock final method in non-final concrete class?