【问题标题】:How to mock and unit test javax.persistence.EntityManager and javax.persistence.Query? Getting NullPointerException如何模拟和单元测试 javax.persistence.EntityManager 和 javax.persistence.Query?获取 NullPointerException
【发布时间】:2020-11-09 12:22:22
【问题描述】:

在测试方法时。我遇到了需要向其传递查询的实体管理器。

StringBuilder jpqlQuery=new StringBuilder("select Distinct s.modelCode from Model s where 1=1");
Query query = entityManager.createQuery(jpqlQuery.toString());
    if(myModel != null ) {      
        jpqlQuery.append(" and s.name = :name");
}
if(myModel != null){
    query.setParameter("name", myModel.getFirstName());
}

我可以输入 jpqlquery.append 条件,但无法进入 query.setParameter。

我得到 NullPointerException Query query = entityManager.createQuery(jpqlQuery.toString());

下面是我的测试方法:

@Test
public void testGetModelNameDetails() {
    List<String> results = new ArrayList<>();
    ModelDTO myModel = Mockito.mock(ModelDTO.class);
    StringBuilder jpqlQuery = new StringBuilder("select Distinct s.modelCode from Model s where 1=1");
    when(myModel.getFirstName()).thenReturn("Downtown");
    when(em.createQuery(jpqlQuery.toString())).thenReturn(query);
    when(query.getResultList()).thenReturn(results);
    serviceImpl.getNameDetails(myModel);
}

when(em.createQuery(jpqlQuery.toString())).thenReturn(query); 行调试时,我可以看到查询对象是模拟的查询对象。 但是在被测试的方法内部,即 在这一行:Query query = entityManager.createQuery(jpqlQuery.toString()); 查询对象为空。

因此我在 query.setParameter("name", myModel.getFirstName()); 得到 NullPointerException

在测试类开始时,我正在模拟 entityManager 和查询 @嘲笑 EntityManager entityManager;

@Mock
Query query;

@Before
public void setUp() {

    MockitoAnnotations.initMocks(this);
    entityManager = Mockito.mock(em.class);
    query = Mockito.mock(Query.class);
}

我在这里遗漏了什么或做错了什么?

【问题讨论】:

  • 你确定两个字符串相等吗?在您的方法中,您在从字符串中创建查询后向字符串附加了一些内容,这是一个错字吗?
  • 是的,两个字符串是相等的。如果适合,您可以忽略 append 方法。没有它也会发生错误。问题是:在when(em.createQuery(jpqlQuery.toString())).thenReturn(query); 行调试时我可以看到查询对象是模拟查询对象。但是在被测试的方法内部,即在这一行:Query query = entityManager.createQuery(jpqlQuery.toString()); 查询对象为空。并且 entityManager 的模拟对象到达了正在测试的方法内部。
  • 您是否已经尝试过:when(em.createQuery(Mockito.eq(jpqlQuery.toString()))).thenReturn(query); ?
  • 是的,同样的事情

标签: java unit-testing junit mockito entitymanager


【解决方案1】:

解决了! when(entityManager.createQuery(Mockito.anyString())).thenReturn(query);

【讨论】:

  • 小心使用anyString,它会检查方法接收的参数值。它只是一个字符串类类型检查。这意味着如果某些更改触发了 if 语句,然后触发“jpqlQuery.append(” and s.name = :name")”,它会保持匹配并返回模拟值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多