title: How to properly mock EntityManager.detach
body: <p><strong>Updated</strong></p>
  <p>I could use some help with the proper way to mock EntityManager.detach() in Spring using Mockito.  I'm not sure what to put in the doAnswer block in the test.  Everything I've tried results in an NPE on the em.detach() call in the service impl.  The debugger shows that both em and existing are valid, non-null objects.  (Shared EntityManager proxy for target factory [javax.persistence.EntityManagerFactory#0 bean]).  Full NPE stack trace added.</p>
  <p>Service class</p>
  <pre><code>@Service
  @Transactional
  public class MyEntityServiceImpl implements MyEntityService {
    private final MyDao dao;
    
    @PersistenceContext
    private EntityManager em;
    
    public MyEntityServiceImpl(MyDao dao) {
      super();
      this.dao = dao;
    }
    public MyDto update(MyDto dto) {
      // check preconditions for null and empty
      
      MyEntity existing = dao.findByBusinessKey(dto.getBusinessKey());
      if(existing == null) {
          throw new NotFoundException();
      }
      em.detach(existing) // NPE on this line during unit test.  
      
      // business logic
      
      MyEntity saved = dao.save(existing);
    }
  </code></pre>
  <p>Unit test</p>
  <pre><code>@SpringJUnitConfig()
  class ServiceImplTest {
    @Autowired
    private MyEntityServiceImpl service;
    
    @MockBean
    private MyDao dao;
    
    @MockBean
    EntityManagerFactory emf;
    
    @MockBean
    EntityManager em;
    
    @Test
    public void givenValidEntity_whenUpdate_thenNoException() {
      MyDto existing = MyDto.builder.businessKey(&quot;valid business key&quot;).build();
      when(dao.findByBusinessKey(any(MyDto.class)).thenReturn(existing);
      doAnswer( invocation -&gt; {
          // what goes in here??!?!?!
      }).when(em).detach(any(MyDto.class));
      
      assertDoesNotThrow(() -&gt; {
          service.update(existing);
      });
    }
  }
  </code></pre>
  <p>Stack Trace</p>
  <pre><code>    org.opentest4j.AssertionFailedError: Unexpected exception thrown: java.lang.NullPointerException
      at org.junit.jupiter.api.AssertDoesNotThrow.createAssertionFailedError(AssertDoesNotThrow.java:83)
      at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:54)
      at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:37)
      at org.junit.jupiter.api.Assertions.assertDoesNotThrow(Assertions.java:3060)
      at MyEntityServiceImpl.givenValidEntity_whenUpdate_thenNoException(MyEntityServiceImpl.java:126)
      at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.base/java.lang.reflect.Method.invoke(Method.java:566)
      at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
      at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
      at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
      at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
      at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
      at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
      at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$135/0x0000000075d4ab40.apply(Unknown Source)
      at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
      at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall$$Lambda$136/0x0000000075b80880.apply(Unknown Source)
      at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
      at org.junit.jupiter.engine.execution.ExecutableInvoker$$Lambda$335/0x0000000075f81e80.apply(Unknown Source)
      at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
      at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
      at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
      at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
      at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
      at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
      at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
      at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$452/0x0000000075ba46f0.execute(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
      at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
      at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
      at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$215/0x0000000075d4fad0.execute(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$214/0x0000000075bb9a70.invoke(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$213/0x0000000075bb9600.execute(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
      at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService$$Lambda$219/0x0000000075d52eb0.accept(Unknown Source)
      at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
      at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$215/0x0000000075d4fad0.execute(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$214/0x0000000075bb9a70.invoke(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$213/0x0000000075bb9600.execute(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
      at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService$$Lambda$219/0x0000000075d52eb0.accept(Unknown Source)
      at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
      at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$215/0x0000000075d4fad0.execute(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$214/0x0000000075bb9a70.invoke(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$213/0x0000000075bb9600.execute(Unknown Source)
      at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
      at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
      at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
      at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
      at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
      at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
      at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
      at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
      at org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$179/0x0000000075c7b430.accept(Unknown Source)
      at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
      at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
      at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
      at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:84)
      at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
      at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
  Caused by: java.lang.NullPointerException
      at java.base/java.lang.reflect.Method.invoke(Method.java:559)
      at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311)
      at com.sun.proxy.$Proxy45.detach(Unknown Source)
      at impl.MyEntityServiceImpl.update(MyEntityServiceImpl.java:107)
      at MyEntityServiceImpl.lambda$0(MyEntityServiceImpl.java:127)
      at MyEntityServiceImpl$$Lambda$463/0x00000000765fc660.execute(Unknown Source)
      at org.junit.jupiter.api.AssertDoesNotThrow.assertDoesNotThrow(AssertDoesNotThrow.java:50)
      ... 86 more
  </code></pre>