Search code examples
spring-bootjunitmockitojunit5

Mockito calling its mock when Mockito.when() is called?


Setup like this:

@BeforeEach
void setUp() {
  mockAddressClient();
}

private void mockAddressClient() {
  Mockito
    .when(addressClient.addAddress(Mockito.any()))
    .thenAnswer(
      in -> {
        de.vbg.suvi.api.address.v1.model.Address adr = in.getArgument(0);
        de.vbg.suvi.api.address.v1.model.ValueAddress values = adr.getValues();
        AddressResponse addressResponse =
          new AddressResponse()
            .id(UUID.randomUUID())
            .streetLine1(values.getStreetLine1())
            .streetLine2(values.getStreetLine2())
            .streetNumber(values.getStreetNumber())
            .zipCode(values.getZipCode())
            .city(values.getCity())
            .country(values.getCountry());
        addresses.put(addressResponse.getId(), addressResponse);
        return new ResponseEntity<>(addressResponse, HttpStatus.CREATED);
    });
}

@Test
void postFullAccidentReport_firstWitnessAddressStreetNumberMissing() {
  /*
   * Given
   */
  final String placeId = UUID.randomUUID().toString();
  AccidentReport accidentReport = createFullAccidentReport();
  accidentReport.getFirstWitness().getPerson().getAddress().setPlaceId(placeId);
  accidentReport.getFirstWitness().getPerson().getAddress().setValues(null);
  Mockito.when(addressClient.addAddress(Mockito.argThat(a -> a.getPlaceId().equals(placeId))))
    .thenThrow(
      new ValidationException(
        List.of(
          new SuviFieldValidationError(
            ViolationCode.INVALID, "message", "streetNumber"))));

  /*
   * When
   */
  ResponseEntity<ValidationProblem> response =
    postAccidentReport(accidentReport, ValidationProblem.class);

  /*
   * Then
   */
  Assertions.assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
  Assertions.assertNotNull(response.getBody());
  ValidationProblem validationProblem = response.getBody();
  FieldViolation fieldViolation = validationProblem.getViolations().get(0);
  Assertions.assertEquals(
    "firstWitness.person.address.placeId.streetNumber", fieldViolation.getField());
}

Now when running my test I receive a NullPointerException in the method mockAddressClient() on adr.getValues(). Checking the call trace it looks as if the NPE is thrown on the line Mockito.when() in my test method. As if the Mockito is calling its own mock.

Has somebody experienced this before? Is the setup wrong? What is the way around it?

EDIT: Annotation for the Mock is @MockBean. Return type of addAddress() is ResponseEntity<AddressResponse>.

java.lang.NullPointerException
   at de.vbg.suvi.claim.api.ClaimControllerTest.lambda$mockAddressClient$18(ClaimControllerTest.java:2308 undefined)
   at org.mockito.internal.stubbing.StubbedInvocationMatcher.answer(StubbedInvocationMatcher.java:40 undefined)
   at org.mockito.internalr.MockHandlerImpl.handle.handle(MockHandlerImpl.java:99 undefined)
   at org.mockito.internalr.NullResultGuardian.handle.handle(NullResultGuardian.java:29 undefined)
   at org.mockito.internalr.InvocationNotifierHandler.handle.handle(InvocationNotifierHandler.java:33 undefined)
   at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82 undefined)
   at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:56 undefined)
   at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor$DispatcherDefaultingToRealMethod.interceptAbstract(MockMethodInterceptor.java:157 undefined)
   at de.vbg.suvi.claim.clients.AddressClient$MockitoMock$2090955218.addAddress(Unknown Source)
   at de.vbg.suvi.claim.api.ClaimControllerTest.postFullAccidentReport_firstWitnessAddressStreetNumberMissing(ClaimControllerTest.java:825 undefined)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62 undefined)
   at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43 undefined)
   at java.base/java.lang.reflect.Method.invoke(Method.java:564 undefined)
   at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688 undefined)
   at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131 undefined)
   at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149 undefined)
   at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140 undefined)
   at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84 undefined)
   at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115 undefined)
   at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45 undefined)
   at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37 undefined)
   at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104 undefined)
   at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98 undefined)
   at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206 undefined)
   at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131 undefined)
   at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129 undefined)
   at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84 undefined)
   at java.base/java.util.ArrayList.forEach(ArrayList.java:1511 undefined)
   at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129 undefined)
   at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84 undefined)
   at java.base/java.util.ArrayList.forEach(ArrayList.java:1511 undefined)
   at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129 undefined)
   at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127 undefined)
   at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126 undefined)
   at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84 undefined)
   at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32 undefined)
   at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57 undefined)
   at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67 undefined)
   at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52 undefined)
   at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96 undefined)
   at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75 undefined)
   at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99 undefined)
   at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79 undefined)
   at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75 undefined)
   at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61 undefined)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62 undefined)
   at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43 undefined)
   at java.base/java.lang.reflect.Method.invoke(Method.java:564 undefined)
   at org.gradle.internal.ReflectionDispatch.dispatch.dispatch(ReflectionDispatch.java:36 undefined)
   at org.gradle.internal.ReflectionDispatch.dispatch.dispatch(ReflectionDispatch.java:24 undefined)
   at org.gradle.internal.ContextClassLoaderDispatch.dispatch.dispatch(ContextClassLoaderDispatch.java:33 undefined)
   at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94 undefined)
   at com.sun.proxy.$Proxy5.stop(Unknown Source)
   at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:133 undefined)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62 undefined)
   at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43 undefined)
   at java.base/java.lang.reflect.Method.invoke(Method.java:564 undefined)
   at org.gradle.internal.ReflectionDispatch.dispatch.dispatch(ReflectionDispatch.java:36 undefined)
   at org.gradle.internal.ReflectionDispatch.dispatch.dispatch(ReflectionDispatch.java:24 undefined)
   at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182 undefined)
   at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164 undefined)
   at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414 undefined)
   at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64 undefined)
   at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48 undefined)
   at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130 undefined)
   at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630 undefined)
   at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56 undefined)
   at java.base/java.lang.Thread.run(Thread.java:832 undefined)

Solution

  • With this construction your thenThrow setup indeed calls the method on the mock, instead of setting it up.

    You can use the alternative mock setup to fix this, for example (incomplete example for readability):

    Mockito.doThrow(myException).when(addressClient).addAddress(matchers)
    

    Validated this in one of my own projects with Mockito.

    If Mockito then complains that this mocking constuction is deemed unnecessary (a matcher on any and a specific matcher on argThat), you can set it up with lenient enabled:

    Mockito.lenient().doThrow(myException).when(addressClient).addAddress(matchers)
    

    From https://www.baeldung.com/mockito-unnecessary-stubbing-exception

    This is basically because in your @BeforeEach you setup a general answer, and in the specific test postFullAccidentReport_firstWitnessAddressStreetNumberMissing you want it to throw an Exception instead. So the first setup is actually not used in this test method.

    My guess is that you have other test methods that do use the general setup, but it would be cleaner to have the correct setup for each method.