首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模拟EntityManager

模拟EntityManager
EN

Stack Overflow用户
提问于 2015-04-06 18:26:59
回答 2查看 2.6K关注 0票数 1

我在模仿EntityManager的时候得到了NPE,下面是我的代码。

代码语言:javascript
复制
@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);
    }
}

我的实体类

代码语言:javascript
复制
@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);
    }
}

我的测试类

代码语言:javascript
复制
@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 is not null (以及其他参数REPLICATION_DOMAIN,SOURCE_NODE_INDEX,NODE_CHANGE_NUMDER not null),而em.createNamedQuery("NodeChangeDelta.findIdByNaturalKey",String.class)为null。

EN

回答 2

Stack Overflow用户

发布于 2015-04-06 20:20:11

在mockito wiki上:Don't mock types you don't own !

这不是一条硬线,但越过这条线可能会产生影响!(它很可能会。)

  1. 想象一下模仿第三方库的代码。在第三个库的特定升级之后,逻辑可能会有一些变化,但测试套件将执行得很好,因为它是模拟的。因此,后来,认为一切都很好,构建墙毕竟是绿色的,软件部署和...
  2. 这可能是当前设计与第三方库解耦不够的迹象。
  3. 另外一个问题是第三方库可能很复杂,甚至需要很多mock才能正常工作。这导致了过度指定的测试和复杂的fixture,这本身就损害了紧凑和可读性的目标。或者用于没有充分覆盖代码的测试,因为模拟外部系统很复杂。

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

没有控件的模拟类型可以被认为是(模拟)反模式。虽然EntityManager几乎是标准的,但人们不应该认为在即将到来的JDK / JSR版本中不会有任何行为变化(它已经在API的其他部分发生过很多次,看看JDK发行说明就知道了)。此外,真正的实现可能在其行为中具有难以模仿的微妙之处,测试可能是绿色的,但生产tomcats是着火的(真实故事)。

我的观点是,如果代码需要模拟我不拥有的类型,设计应该尽快更改,这样我、我的同事或该代码的未来维护者就不会落入这些陷阱。

此外,wiki链接到其他博客条目,这些条目描述了他们在尝试模拟他们无法控制的类型时遇到的问题。

相反,我真的建议每个人在测试与另一个系统的集成时,不要使用模拟。我相信对于数据库来说,Arquillian是最好的选择,这个项目看起来相当活跃。

改编自我的答案:

票数 1
EN

Stack Overflow用户

发布于 2015-04-06 20:00:12

在Mockito中,对未显式配置的mock进行的任何方法调用都将返回null。因此,在findIdByNaturalKey中,em.createNamedQuery返回null,因此在setParameter上返回NPE。您需要将其配置为RETURN_MOCKS

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29469442

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档