Reputation: 7394
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
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
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