javaunit-testingnullpointerexceptionmockito

Mockito null pointer with TypedQuery?


I am using Mockito to mock the result set of a Java Persistence Query:

Code being mocked:

 public void queryMethod(String name){
  List<Person> result = persistence.entityManager().createQuery(
                    "Select p from Person p +
                            " where p.name= :uniqueId" , Person.class)
                    .setParameter("name", name)
                    .getResultList();

 }

test code:

String name  = "anyName";
Person person = mock(Person.class);
List<Person> personList = new ArrayList<>();
personList.add(person);

    TypedQuery query = mock(TypedQuery.class);
    when(entityManager.createQuery(anyString(), Matchers.<Class<Object>>anyObject())).thenReturn(query);
    when(query.setParameter(1, name)).thenReturn(query);
    when(query.getResultList()).thenReturn(personList);

I am getting a null pointer error on the line:

List<Person> result = persistence.entityManager().createQuery(

What could be causing this?


Solution

  • Your bug is here:

    when(query.setParameter(1, name)).thenReturn(query);
    

    it should be

    when(query.setParameter("name", name)).thenReturn(query);
    

    Indeed in your request you call .setParameter("name", name) not .setParameter(1, name) so you don't mock the right method and by default a non mocked method will return null which is why you get a NPE.

    Anyway it doesn't seem to be the right approach as it is very error prone since you need to couple too much your test case with your implementation, you should rather move your query in a dedicated method and then mock this method.

    We should have something like:

    public List<Person> findByName(String name) {
        return persistence.entityManager().createQuery(
                    "Select p from Person p +
                            " where p.name= :uniqueId" , Person.class)
                    .setParameter("name", name)
                    .getResultList();
    }
    

    Then you will be able to mock this method as next:

    Person person = mock(Person.class);
    List<Person> personList = new ArrayList<>();
    personList.add(person);
    
    MyDAO dao = mock(MyDAO.class);
    when(dao.findByName(name)).thenReturn(personList);