Mockito 空指针与 TypedQuery?

jav*_*999 1 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" , Person.class)
                    .setParameter("name", name)
                    .getResultList();

 }
Run Code Online (Sandbox Code Playgroud)

测试代码:

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);
Run Code Online (Sandbox Code Playgroud)

我收到空指针错误:

List<Person> result = persistence.entityManager().createQuery(
Run Code Online (Sandbox Code Playgroud)

可能是什么原因造成的?

Nic*_*tto 5

你的错误在这里:

when(query.setParameter(1, name)).thenReturn(query);
Run Code Online (Sandbox Code Playgroud)

它应该是

when(query.setParameter("name", name)).thenReturn(query);
Run Code Online (Sandbox Code Playgroud)

事实上,在您的请求中,您.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();
}
Run Code Online (Sandbox Code Playgroud)

然后您将能够模拟此方法,如下所示:

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

MyDAO dao = mock(MyDAO.class);
when(dao.findByName(name)).thenReturn(personList);
Run Code Online (Sandbox Code Playgroud)