gpt4 book ai didi

testing - 模拟实体管理器

转载 作者:行者123 更新时间:2023-11-28 20:41:54 24 4
gpt4 key购买 nike

我在模拟 EntityManager 时遇到 NPE,下面是我的代码,

@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 不为空),而 em.createNamedQuery("NodeChangeDelta.findIdByNaturalKey", String.class) 为空。

最佳答案

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

This is not a hard line, but crossing this line may have repercussions! (it most likely will.)

  1. Imagine code that mocks a third party lib. After a particular upgrade of a third library, the logic might change a bit, but the test suite will execute just fine, because it's mocked. So later on, thinking everything is good to go, the build-wall is green after all, the software is deployed and... Boom
  2. It may be a sign that the current design is not decoupled enough from this third party library.
  3. Also another issue is that the third party lib might be complex and require a lot of mocks to even work properly. That leads to overly specified tests and complex fixtures, which in itself compromises the compact and readable goal. Or to tests which do not cover the code enough, because of the complexity to mock the external system.

Instead, the most common way is to create wrappers around the external lib/system, though one should be aware of the risk of abstraction leakage, where too much low level API, concepts or exceptions, goes beyond the boundary of the wrapper. In order to verify integration with the third party library, write integration tests, and make them as compact and readable as possible as well.

你没有控制权的 Mock 类型可以被认为是 (mocking) 反模式。虽然 EntityManager 几乎是标准,但不应认为在即将发布的 JDK/JSR 版本中不会有任何行为变化(它已经在其他部分发生过多次) API,只需查看 JDK 发行说明)。此外,真实的实现在行为上可能有难以模仿的微妙之处,测试可能是绿色的,但生产 tomcat 却着火了(真实故事)。

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

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

相反,我真的建议大家在测试与另一个系统的集成时不要使用模拟。我相信对于数据库的东西,Arquillian是要进行的事情,该项目似乎非常活跃。


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

关于testing - 模拟实体管理器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29469442/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com