Home > database >  Multiselect Criteria Query returning NullPointerException in unit tests using mockito framework
Multiselect Criteria Query returning NullPointerException in unit tests using mockito framework

Time:10-10

@Transactional
    public List<Object[]> findAll() {
        Session session = sessionFactory.getCurrentSession();
        CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
        CriteriaQuery<Object[]> query = criteriaBuilder.createQuery(Object[].class);
        Root<TableA> aRoot = query.from(TableA.class);
        Root<TableB> bRoot = query.from(TableB.class);
        Root<TableC> cRoot = query.from(TableC.class);
        query.multiselect(aRoot.get("type"), cRoot.get("fieldId"), aRoot.get("fieldId"),
                aRoot.get("fieldId"), aRoot.get("name"), aRoot.get("name"),
                aRoot.get("average"), aRoot.get("average"));
        query.where(criteriaBuilder.equal(bRoot.get("fieldId"), cRoot.get("fieldId")),
                criteriaBuilder.in(bRoot.<String>get("type")).value("ABC").value("DFG"),<-----NullPointerException Here
                criteriaBuilder.equal(bRoot.get("type"), aRoot.get("type")));
        query.distinct(true);
       return session.createQuery(query).getResultList();
    }

This method has been censored but it works perfectly. My problem is completing the unit test to cover the code so I can push to our repository.

    @Before
    @Override
    public void setup() {
        super.setup();
    }

    @InjectMocks
    @Spy
    Dao dao;

    @Mock
    SessionFactory sessionFactory;

    @Mock
    Session mockSession;

    @Mock
    CriteriaBuilder criteriaBuilder;

    @Mock
    CriteriaQuery<Object> query;

    @Mock
    Root<TableA> mockARoot;

    @Mock
    Root<TableB> mockBRoot;

    @Mock
    Root<TableC> mockCRoot;

    @Mock
    Query<Object> result;

@Test
    public void findAll() {
        Mockito.when(sessionFactory.getCurrentSession()).thenReturn(mockSession);
        Mockito.when(mockSession.getCriteriaBuilder()).thenReturn(criteriaBuilder);
        Mockito.when(criteriaBuilder.createQuery(Mockito.anyObject())).thenReturn(query);
        Mockito.when(query.from(TableA.class)).thenReturn(mockARoot);
        Mockito.when(query.from(TableB.class)).thenReturn(mockBRoot);
        Mockito.when(query.from(TableC.class)).thenReturn(mockCRoot);
        Mockito.when(mockSession.createQuery(query)).thenReturn(result);
        dao.findAll();
    }

I believe the In clause is expecting an expression or predicate. Do I need to mock and pass in other interfaces to get this to work? I would really like to add this style of query construction to our code-base but I cannot complete the junit test. Any assistance would be much appreciated!

CodePudding user response:

As far as I know, people dont use mockito to test the Dao layer. It should be tested as an integration test.

Regarding mockito, we should mock the layers only where the object other classes are used within the method for example in your code, the variable sessionFactory is an object of other class used in this findAll method in Dao.

We should mock that class and not the variables which initialized within the mehtod(local variables).

P.S, full error stack trace would be more helpful to address

CodePudding user response:

You don't mock all your methods calls... query.multiselect, aRoot.get("fieldId")... As you are mocking your object, you are reponsible to mock all the needed method calls.

  • Related