Java 带TypedQuery的Mockito空指针?

Java 带TypedQuery的Mockito空指针?,java,unit-testing,nullpointerexception,mockito,Java,Unit Testing,Nullpointerexception,Mockito,我使用Mockito模拟Java持久性查询的结果集: 正在模拟的代码: public void queryMethod(String name){ List<Person> result = persistence.entityManager().createQuery( "Select p from Person p + " where p.name= :uniqueId" , P

我使用Mockito模拟Java持久性查询的结果集:

正在模拟的代码:

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

 }
public void查询方法(字符串名称){
列表结果=persistence.entityManager().createQuery(
“从人员p中选择p+
“其中p.name=:uniqueId”,Person.class)
.setParameter(“名称”,名称)
.getResultList();
}
测试代码:

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);
String name=“anyName”;
Person=mock(Person.class);
List personList=新建ArrayList();
personList.add(person);
TypedQuery=mock(TypedQuery.class);
当(entityManager.createQuery(anyString(),Matchers.anyObject())。然后返回(查询);
when(query.setParameter(1,name))。然后返回(query);
当(query.getResultList())。然后返回(personList);
我在该行上收到一个空指针错误:

List<Person> result = persistence.entityManager().createQuery(
List result=persistence.entityManager().createQuery(
是什么导致了这种情况?

您的错误在这里:

when(query.setParameter(1, name)).thenReturn(query);
应该是

when(query.setParameter("name", name)).thenReturn(query);
实际上,在您的请求中,您调用
.setParameter(“name”,name)
而不是
.setParameter(1,name)
,因此您没有模拟正确的方法,默认情况下,非模拟的方法将返回
null
,这就是您获得NPE的原因

无论如何,这似乎不是正确的方法,因为它非常容易出错,因为您需要将太多的测试用例与您的实现结合起来,您应该将查询移动到专用方法中,然后模拟此方法

我们应该有这样的东西:

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();
}
公共列表findByName(字符串名称){
返回persistence.entityManager().createQuery(
“从人员p中选择p+
“其中p.name=:uniqueId”,Person.class)
.setParameter(“名称”,名称)
.getResultList();
}
然后,您可以将此方法模拟为下一个:

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

MyDAO dao = mock(MyDAO.class);
when(dao.findByName(name)).thenReturn(personList);
Person-Person=mock(Person.class);
List personList=新建ArrayList();
personList.add(person);
MyDAO=mock(MyDAO.class);
when(dao.findByName(name)).thenReturn(personList);
您的错误在这里:

when(query.setParameter(1, name)).thenReturn(query);
应该是

when(query.setParameter("name", name)).thenReturn(query);
实际上,在您的请求中,您调用
.setParameter(“name”,name)
而不是
.setParameter(1,name)
,因此您没有模拟正确的方法,默认情况下,非模拟的方法将返回
null
,这就是您获得NPE的原因

无论如何,这似乎不是正确的方法,因为它非常容易出错,因为您需要将太多的测试用例与您的实现结合起来,您应该将查询移动到专用方法中,然后模拟此方法

我们应该有这样的东西:

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();
}
公共列表findByName(字符串名称){
返回persistence.entityManager().createQuery(
“从人员p中选择p+
“其中p.name=:uniqueId”,Person.class)
.setParameter(“名称”,名称)
.getResultList();
}
然后,您可以将此方法模拟为下一个:

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

MyDAO dao = mock(MyDAO.class);
when(dao.findByName(name)).thenReturn(personList);
Person-Person=mock(Person.class);
List personList=新建ArrayList();
personList.add(person);
MyDAO=mock(MyDAO.class);
when(dao.findByName(name)).thenReturn(personList);

可能重复的@GhostCat你是什么意思?请解释一下也许我a的速度有点太快了。但问题是:在这一行中,至少有两个对象可以为你提供NPE。a)持久性B)调用entityManager()的结果C)然后是createQuery()的结果.Long story short:您必须确保每个调用都返回不为null的内容。请尝试使用when(query.setParameter(“name”,name)).thenReturn(query);而不是when(query.setParameter(1,name))。thenReturn(query);您确定persistence.entityManager()返回一些内容?可能是@GhostCat的重复项你是什么意思?请解释一下也许我a的速度有点太快了。但问题是:在这一行中,至少有两个对象可以为你提供NPE。a)持久性B)调用entityManager()的结果C)然后是createQuery()的结果.Long story short:您必须确保每个调用都返回非null的内容。请尝试使用when(query.setParameter(“name”,name)).thenReturn(query);而不是when(query.setParameter(1,name))。thenReturn(query);是否确定persistence.entityManager()返回内容?