2015-04-06 123 views
1

我越来越NPE而嘲讽的EntityManager,下面是我的代码,嘲讽的EntityManager

@Stateless 
public class NodeChangeDeltaQueryBean implements NodeChangeDeltaQueryLocal { 

    @PersistenceContext 
    private EntityManager em; 
    @Override 
    public String findIdByNaturalKey(final String replicationDomain, final int sourceNodeIndex, 
            final int nodeChangeNumber) { 
     List<String> result = 
      NodeChangeDelta.findIdByNaturalKey(this.em, replicationDomain, sourceNodeIndex, 
       nodeChangeNumber).getResultList(); 
     return result.isEmpty() ? null : result.get(0); 
    } 
} 

我的实体类

@Entity 
public class NodeChangeDelta implements Serializable, Cloneable, GeneratedEntity, KeyedEntity<String> { 

public static TypedQuery<String> findIdByNaturalKey(final EntityManager em, final String replicationDomain, final int sourceNodeIndex, final int nodeChangeNumber) { 
     return em.createNamedQuery("NodeChangeDelta.findIdByNaturalKey", String.class) 
      .setParameter("replicationDomain", replicationDomain) 
      .setParameter("sourceNodeIndex", sourceNodeIndex) 
      .setParameter("nodeChangeNumber", nodeChangeNumber); 
    } 
} 

我的测试类

@RunWith(MockitoJUnitRunner.class) 
public class NodeChangeDeltaQueryBeanTest { 

    @InjectMocks 
    NodeChangeDeltaQueryBean nodeChangeDeltaQueryBean; 

    @Mock 
    EntityManager em; 

@Test 
    public void testFindIdByNaturalKey() { 
     this.addNodeChangeDelta(); 
     this.nodeChangeDeltaQueryBean.findIdByNaturalKey(this.REPLICATION_DOMAIN, 
      this.SOURCE_NODE_INDEX, this.NODE_CHANGE_NUMDER); 
    } 
} 

在调试EM不null(还有其他参数REPLICATION_DOMAIN, SOURCE_NODE_INDEX,NODE_CHANGE_NUMDER不为空)在Entit y类,而em.createNamedQuery(“NodeChangeDelta.findIdByNaturalKey”,String.class)为null。

+0

难道你希望你的模拟执行的实际查询?这是行不通的。它不知道你的数据源,持久化上下文,命名查询等。 – 2015-04-06 10:34:05

回答

0

在Mockito中,任何未明确配置的模拟方法调用总是返回null。因此在findIdByNaturalKey,em.createNamedQuery正在返回null等NPE在setParameter。您需要将其配置为RETURN_MOCKS

此外,我不确定@InjectMocks是否支持@PersistenceContext。如果没有,则em可能为空。如果是这样,请让我知道,以上是你的问题。

+0

'@InjectMocks'不是spring/jee意识到的,它只是试图找到一个匹配类型。它不是一个真正的依赖注入框架。 – Brice 2015-04-06 12:21:59

1

在维基的Mockito:Don't mock types you don't own !

这不是一个难行,但越过这条线可能有反响! (很有可能)。

  1. 想象一下嘲笑第三方库的代码。在第三个库的特定升级之后,逻辑可能会改变一点,但测试套件将会执行得很好,因为它被嘲弄。所以,以后想,一切都很好走,墙壁是绿色的,毕竟软件部署和... 繁荣
  2. 这可能是一个迹象,目前的设计是不够脱离这第三党的图书馆。
  3. 另一个问题是,第三方库可能很复杂,需要大量的模拟才能正常工作。这会导致过度指定的测试和复杂的装置,这本身就影响了紧凑且可读的目标。或者由于模拟外部系统的复杂性,测试不足以覆盖代码。

相反,最常见的方法是在外部库/系统周围创建包装,虽然人们应该意识到抽象泄漏的风险,其中太多低级API,概念或例外超出边界的包装。为了验证与第三方库的集成,编写集成测试,并使其尽可能紧凑和可读。

,你没有控制模拟类型可以被认为是(嘲讽)反模式。虽然EntityManager几乎是标准,但我们不应该认为即将到来的JDK/JSR版本中不会有任何行为改变(它已经在API的其他部分发生过无数次了,请看JDK发行说明)。再加上真正的实现可能在他们的行为中微妙不易被嘲笑,测试可能是绿色的,但生产的雄猫队着火了(真实的故事)。我的观点是,如果代码需要模拟一种我不拥有的类型,那么设计应该改变asap,所以我,我的同事或这个代码的未来维护者不会落入这些陷阱。

此外,wiki链接到其他博客条目,描述他们试图模拟他们没有控制的类型时遇到的问题。

相反,我真的建议大家不要使用模拟当测试与另一个系统的集成。我相信数据库的东西,Arquillian是要走的东西,该项目似乎相当活跃。


从我的回答改编:https://stackoverflow.com/a/28698223/48136