嘲讽的EntityManager(Mocking EntityManager)

2019-10-22 12:44发布

我越来越NPE而嘲讽的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不为空(也可等论调REPLICATION_DOMAIN,SOURCE_NODE_INDEX,NODE_CHANGE_NUMDER NOT NULL)在实体类,而em.createNamedQuery( “NodeChangeDelta.findIdByNaturalKey”,String.class)为空。

Answer 1:

在维基的Mockito: 不要嘲笑你不自己的类型!

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

  1. 试想一下,嘲笑第三方的lib代码。 第三库的特定升级后,逻辑可能会改变一点,但因为它嘲笑测试套件将执行就好了。 所以后来,以为一切都很好走,毕竟,软件部署和构建墙是绿色的......
  2. 这可能是一个迹象,是不是从这个第三方库解耦目前的设计不够。
  3. 此外另一个问题是,第三方的lib可能是复杂的,需要大量的嘲笑的,甚至正常工作。 这导致过度指定的测试和复杂的灯具,这本身就损害了紧凑和可读性的目标。 或者其中不包括因复杂嘲笑外部系统的代码足够,测试。

相反,最常见的方式是围绕着外部的lib /系统创建包装,但应该意识到抽象泄漏,其中太多底层API,概念或异常的风险,去包装的边界之外。 为了验证与第三方库集成,写集成测试,并让他们为紧凑和可读性尽可能好。

你没有控制模拟类型可以被认为是( 嘲讽 )反模式。 虽然EntityManager是相当多的标准 ,人们不应该认为有将不会在即将到来的JDK / JSR版本的任何行为改变(这已经发生了很多的时间在API的另一部分,只是看在JDK发行说明)。 再加上真正的实现可能有他们的行为细微之处也很难被嘲笑,测试可能是绿色的,但是生产雄猫着火了(真实的故事)。

我的观点是,如果代码需要嘲笑一个类型我没有自己的设计应尽快改变,所以我,我的同事或者这段代码以后的维护者不会在这些陷阱下降。

另外,维基链接描述,当他们试图嘲笑类型,他们没有控制他们有问题的其他博客条目。

相反,我真的劝告大家与其他系统集成测试时, 不要使用模拟 。 我相信,数据库的东西, 的Arquillian是要走的事情,该项目似乎是相当活跃。


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



Answer 2:

在的Mockito,在未明确配置一个模拟的任何方法调用,总是返回null 。 因此,在findIdByNaturalKeyem.createNamedQuery将返回null并因此NPE setParameter 。 你需要把它配置到RETURN_MOCKS 。

另外,我不知道,如果@InjectMocks支持@PersistenceContext 。 如果它不那么em可能是零。 如果是的话,请让我知道,上面是你的问题。



文章来源: Mocking EntityManager