java123999
java123999

Reputation: 7394

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?

Upvotes: 1

Views: 8174

Answers (2)

Venkatt Guhesan
Venkatt Guhesan

Reputation: 105

It should be noted that when you implement using the approach that @NicholasFilotto describes as follows:

MyDAO dao = mock(MyDAO.class);

The entire class you are testing gets mocked. This means the Java Coverage on the entire class is zero.

But on the other hand, if you use the approach used by @java123999 where you are mocking the inner parts, then the coverage on that approach will come close to 100%.

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(), Person.class)).thenReturn(query);
when(query.setParameter(1, name)).thenReturn(query);
when(query.getResultList()).thenReturn(personList);

By knowing the difference, you can take the approach that best suits your intent.

Cheers.

Upvotes: 0

Nicolas Filotto
Nicolas Filotto

Reputation: 44965

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);

Upvotes: 5

Related Questions