Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用createQuery()、参数和executeUpdate()模拟Hibernate entityManager_Java_Hibernate_Junit_Mockito_Junit5 - Fatal编程技术网

Java 使用createQuery()、参数和executeUpdate()模拟Hibernate entityManager

Java 使用createQuery()、参数和executeUpdate()模拟Hibernate entityManager,java,hibernate,junit,mockito,junit5,Java,Hibernate,Junit,Mockito,Junit5,我是java单元测试的新手;我有一个使用Hibernate与MySQL数据库交互的应用程序 我有许多使用createQuery方法构建的查询,也有参数,如下所示: 从MyEntity m返回this.entityManager.createQueryfrom,其中param=:param,MyEntity.class .setParameterparam,param .getSingleResult; 我希望避免模拟entityManager对象上的所有后续调用,因为有时我会使用5个以上的参数进

我是java单元测试的新手;我有一个使用Hibernate与MySQL数据库交互的应用程序

我有许多使用createQuery方法构建的查询,也有参数,如下所示:

从MyEntity m返回this.entityManager.createQueryfrom,其中param=:param,MyEntity.class .setParameterparam,param .getSingleResult; 我希望避免模拟entityManager对象上的所有后续调用,因为有时我会使用5个以上的参数进行查询,并且似乎无法方便地模拟每个调用

同样的概念也可以应用于

编辑1

我添加了一个具体的例子来说明我所使用的方法,因为这不是一种管理异常的好方法,但不幸的是,这是一种很平常的方法:

public class MyService {
private EntityManager entityManager;

public MyEntity find(String field ) {
        try{
            return this.entityManager.createQuery("from MyEntity  c where c.field = :field ", MyEntity .class)
                    .setParameter("field ", field )
                    .getSingleResult();
        } catch (NoResultException e) {
            return null;
        } catch (NonUniqueResultException e) {
            logger.error("find", e);
            return null;
        }
    }
}
在本例中,给定entityManager调用的行为,我有不同的分支需要测试。然后我必须模拟该调用的答案来测试该方法的所有行

我发现了什么 我发现的是:

@Mockanswer=Answers.RETURNS\u DEEP\u STUBS 私人实体管理者实体管理者; 这和预期的一样。我可以模仿所有的呼叫链。但是

引自: 警告:常规的干净代码很少需要此功能!留给遗留代码。Mocking a mock返回一个mock,返回一个mock,…,返回一些有意义的东西,暗示违反了德米特定律,或者模仿一个值对象,这是众所周知的反模式

如果上一点还不够,下一点,即后面的几行,显然设置了一个很大的限制: 当链中包含的任何返回类型的方法都无法模拟时(例如:是基元类或最终类),此功能将不起作用。这是因为java类型的系统

第二点意味着,如果我试图以这种方式模拟executeUpdate方法(返回int),它会引发异常

whenentityManager.CreateQueryAstring .setParametereqparam,任意字符串 .执行更新 .然后返回1; 这样我就无法测试与entityManager的交互

问题 我应该如何模拟entityManager上的调用?我似乎不可能一个接一个地嘲笑每一种方法。 使用Answers.RETURNS\u DEEP\u STUBS是错误的吗?如果没有,我如何处理第二个示例?
不要模仿JPAAPI,只需使用适当的测试数据编写集成测试,并针对实际数据执行实际查询,看看是否一切正常。像这样的项目非常容易启动。

不要模仿JPA API,只需使用适当的测试数据编写集成测试,并对实际数据执行实际查询,看看是否一切正常。像这样的项目非常容易启动。

我的建议是专门使用集成测试来测试与EntityManager或任何其他外部低级API交互的代码。试图模拟它进行单元测试是一种浪费时间的行为,而且查询只能使用集成测试进行可靠的测试。如果您对EntityManager API有一个抽象,例如Dao对象,那么您可以轻松地为其他单元测试模拟该层。问题:为什么要在第一个位置模拟实体管理器?为什么不针对数据库进行测试,例如内存中的h2或通过testcontainers启动的完全成熟的数据库?单元测试中的单元不一定意味着类。@crizzis没有dao。服务直接访问entityManager。我将用一个代码示例更新这个问题。请注意,这种模式在数百个类、数千个方法、许多项目中使用,因此无法更改:@Turing85,因为如果我得到了正确的单元测试,就不会涉及数据库或外部api调用之类的内容。但我问是因为我必须学习,所以每一个建议都是一个好的开始!与数据库无关的想法一样好的是,在99%的情况下,您以某种方式绑定到特定的DBMS,例如,ANSI-SQL中没有定义索引,并且抛出的异常至少会在实现之间发生变化。在这方面,我建议使用生产中使用/将使用的实际DBMS测试持久层。当然,这是以用测试数据填充数据库为代价的。我的建议是专门使用集成测试来测试与EntityManager或任何其他外部低级API交互的代码。试图模拟它进行单元测试是一种浪费时间的行为,而且查询只能使用集成测试进行可靠的测试。如果您对EntityManager API有一个抽象,例如Dao对象,那么您可以轻松地为其他单元测试模拟该层。问题:为什么要在第一个位置模拟实体管理器?为什么不针对数据库进行测试,例如内存中的h2或通过testcontainers启动的完全成熟的数据库?单元测试中的单元不一定意味着类。@crizzis没有dao。服务直接访问entityManager。我会更新t
他用一个代码示例提问。请注意,这种模式在数百个类、数千个方法、许多项目中使用,因此无法更改:@Turing85,因为如果我得到了正确的单元测试,就不会涉及数据库或外部api调用之类的内容。但我问是因为我必须学习,所以每一个建议都是一个好的开始!与数据库无关的想法一样好的是,在99%的情况下,您以某种方式绑定到特定的DBMS,例如,ANSI-SQL中没有定义索引,并且抛出的异常至少会在实现之间发生变化。在这方面,我建议使用生产中使用/将使用的实际DBMS测试持久层。当然,这是以用测试数据填充数据库为代价的。谢谢你的回答。那么我不应该在使用entityManager的地方进行单元测试?考虑到我们没有DAOS对DB和服务逻辑进行分割访问。似乎我不能在任何地方进行单元测试,我在不同的服务中与entityManager几乎在任何地方进行交互。考虑到这一点,如果我们使用JPA,而不仅仅是Hibernate,情况会更好,是否可以模拟entityManager方法链来返回单元测试我的方法逻辑所需的内容?在我看来,如果您在后台使用数据库,那么测试仍然可以被视为单元测试,因此只需使用数据库并对其执行查询即可。除非您尝试测试表示层,否则模拟数据层是没有意义的,即使这样,我也不会模拟它。测试真实的东西,虽然它可能会稍微慢一点,但不会太多,会给你更高的信心。好的,谢谢你的建议。如果我理解得很好,我应该单元测试所有不与数据库/entityManager交互的方法,而在集成测试中,我测试所有与之交互的方法。因为服务层的一些方法可以通过API进行测试,其他方法可以在服务的IT类上进行测试,或者这不是一个好的模式?因为我会在不同的地方测试同一个类的方法,可能会让人困惑。很少有真正的单元可以测试。你总是认为一些事情是理所当然的,比如你用来实施测试的事情。该单元通常也使用库,但这是一个集成测试吗?不。当你这样看的时候,单元测试和集成测试之间的区别有些模糊。我认为将测试分为快速和慢速两类更合适。但是相信我,你可以快速使用DBS的测试,所以我个人认为大部分时间都是单元测试。谢谢你的回答。那么我不应该在使用entityManager的地方进行单元测试?考虑到我们没有DAOS对DB和服务逻辑进行分割访问。似乎我不能在任何地方进行单元测试,我在不同的服务中与entityManager几乎在任何地方进行交互。考虑到这一点,如果我们使用JPA,而不仅仅是Hibernate,情况会更好,是否可以模拟entityManager方法链来返回单元测试我的方法逻辑所需的内容?在我看来,如果您在后台使用数据库,那么测试仍然可以被视为单元测试,因此只需使用数据库并对其执行查询即可。除非您尝试测试表示层,否则模拟数据层是没有意义的,即使这样,我也不会模拟它。测试真实的东西,虽然它可能会稍微慢一点,但不会太多,会给你更高的信心。好的,谢谢你的建议。如果我理解得很好,我应该单元测试所有不与数据库/entityManager交互的方法,而在集成测试中,我测试所有与之交互的方法。因为服务层的一些方法可以通过API进行测试,其他方法可以在服务的IT类上进行测试,或者这不是一个好的模式?因为我会在不同的地方测试同一个类的方法,可能会让人困惑。很少有真正的单元可以测试。你总是认为一些事情是理所当然的,比如你用来实施测试的事情。该单元通常也使用库,但这是一个集成测试吗?不。当你这样看的时候,单元测试和集成测试之间的区别有些模糊。我认为将测试分为快速和慢速两类更合适。但是相信我,你可以很快地使用DBS进行测试,所以我个人认为大部分时间都是单元测试。