javahibernatejunit5entitymanagerhibernate-envers

Junit Test with envers


I 've trying to test a service which uses hibernate envers to perform a rollback. Everything is working fine but the test is driving me mad.

This is the beginning of the service:

@Slf4j
@AllArgsConstructor
@Service
public class ObjectRollbackServiceImpl implements ObjectRollbackService {

  @Autowired
  private EntityManager entityManager;

  @Autowired private ObjectRollbackRepository objectRollbackRepository;

  private void restorePreviousVersionOfObject(Long id, Boolean isDelete) {

    AuditReader auditReader = AuditReaderFactory.get(entityManager);

    List<Number> revNumbers = auditReader.getRevisions(ObjectEntity.class, id); 

And this is the test:

class ObjectRollbackServiceTests {

  private static final Long objectId = 1L;
  @InjectMocks
  ObjectRollbackServiceImpl objectRollbackServiceImpl;
  @Mock
  ObjectRollbackRepository objectRollbackRepository;

  @PersistenceUnit
  private EntityManagerFactory entityManagerFactory;


  @Mock
  AuditReader auditReader;


  @BeforeEach
  void setUp() throws Exception {
    MockitoAnnotations.openMocks(this);

  }

  @Test
  void testRestorePreviousVersionOfEditedObjectOk() {
    ObjectEntity object = ObjectEntity.builder().build();
    List<Number> listRevisions = Lists.newArrayList();
    listRevisions.add(1);

    when(auditReader.getRevisions(any(), any(Long.class))).thenReturn(listRevisions);
    when(auditReader.find(any(), any(Long.class), any(Number.class))).thenReturn(object);
    when(objectRollbackRepository.findById(any(Long.class))).thenReturn(Optional.of(object));
    when(objectRollbackRepository.saveAndFlush(any(ObjectEntity.class))).thenReturn(object);
    doNothing().when(objectRollbackRepository).updateAuditDates(any(ZonedDateTime.class)
    , any(Integer.class)
    , any(AuditorBO.class)
    , any(Long.class));

    doNothing().when(objectRollbackRepository).deleteRevisionsNotEqualsToCurrentAndPrevious(any(Integer.class), any(Long.class));

    assertDoesNotThrow(() -> objectRollbackServiceImpl.restorePreviousVersionOfEditedObject(1L));


  }



}

So the problem is that entityManager is null when trying to execute this line:

AuditReader auditReader = AuditReaderFactory.get(entityManager);

What am I missing?


Solution

  • You can try mocking AuditReaderFactory.get to give you the mocked AuditReader instance.

    See this question with its answers for further reference.

    So, in your case it could look something like this (code adapted from one of the answers to the other question):

      @Test
      public void testStaticMockWithVerification() {
        try (MockedStatic<AuditReaderFactory> dummy = Mockito.mockStatic(AuditReaderFactory.class)) {
          dummy.when(() -> AuditReaderFactory.get(Mockito.any(EntityManager.class)))
            .thenReturn(auditReader);
    
          factory.getConnection();
    
        }
      }
    

    And instead of using the @Mock annotation, probably create the Mock ObjectRollbackServiceImpl instance in some setup method or static initialization block, so you can set this static mock up beforehand.