Search code examples
unit-testingmockitojpa-2.0predicatespring-boot-test

Mockito Predicate JPA not run correctly


In Unit Test Class:

    @Mock
    EntityManager entityManager;

    @Mock
    Root<RedFox> redFoxRoot;

    @Mock
    Expression expression;

    @Mock
    Path path;

    @Mock
    Predicate predicate;

    @Test 
    public void filterTest(){
      TypedQuery<RedFox> redFoxQuery = (TypedQuery<RedFox>) Mockito.mock(TypedQuery.class);

      CriteriaQuery<RedFox> redFoxCriteriaQuery = Mockito.mock(CriteriaQuery.class);

      Mockito.when(redFoxCriteriaQuery.where(Mockito.any(Predicate[].class)))
      .thenReturn(redFoxQuery); 
 
      Mockito.when(redFoxCriteriaQuery.orderBy(Mockito.anyList())).thenReturn(redFoxCriteriaQuery);

      CriteriaBuilder builder = Mockito.mock(CriteriaBuilder.class);

      Mockito.when(redFoxRoot.get("isDeleted")).thenReturn(path);

      Mockito.when(path.isNull()).thenReturn(predicate);

      Mockito.when(builder.literal(Mockito.any())).thenReturn(expression);

      Mockito.when(redFoxCriteriaQuery.from(RedFox.class)).thenReturn(redFoxRoot);      
 
      Mockito.when(entityManager.createQuery(redFoxCriteriaQuery)).thenReturn(redFoxQuery);

      List<RedFox> redFoxs = new ArrayList<>();
      RedFox redFox = new RedFox();
      redFox.setTitle("abc");
      redFox.setRedFoxStatus("");
      redFox.setId(UUID.randomUUID());
      redFoxs.add(redFox);
   
      Mockito.when(redFoxQuery.getResultList()).thenReturn(redFoxs);
      
  }

In class service:

     public List<RedFox> filter(){
            CriteriaBuilder builder = em.getCriteriaBuilder();
            CriteriaQuery<RedFox> redFoxCriteriaQuery = builder.createQuery(RedFox.class);
            Root<RedFox> root = redFoxCriteriaQuery.from(RedFox.class);
            redFoxCriteriaQuery.select(root);
            List<Predicate> searchClause = new ArrayList<>();

            searchClause.add(builder.isFalse(root.get("isDeleted")));//root cause error

            Predicate[] searchClauses = searchClause.toArray(Predicate[]::new);
            Query executingQuery = em.createQuery(redFoxCriteriaQuery.where(searchClauses)
                                   .orderBy(orderBys));//Null pointer exception
            List<RedFox> resultData = executingQuery
                    .getResultList();
            ..............................
}

My problem is when I comment the searchClause.add(builder.isFalse(root.get("isDeleted"))), it mean that the searchClauses is empty Array, then the code execute successfully.

But when the search clauses is not empty, then redFoxCriteriaQuery.where(searchClauses) not use the result I mocked but return null, and it will cause the null pointer exception.

I've been tucked 2 days but still don't know why so please help me with this issue.


Solution

  • Change

    Mockito.when(redFoxCriteriaQuery.where(Mockito.any(Predicate[].class)))
          .thenReturn(redFoxQuery);
    

    to

    Mockito.when(redFoxCriteriaQuery.where((Predicate[].class) Mockito.any()))
          .thenReturn(redFoxQuery); 
    

    So, it can work with any non null object. But if you write Mockito.any(Predicate[].class), then it just compare 2 array with type Predicate. And of course, 2 array cannot equal although all the elements in each array are equal.