Hibernate事实:集成测试策略

我喜欢集成测试,这是检查Hibernate生成哪些幕后花絮SQL查询的好方法。 但是集成测试需要运行的数据库服务器,这是您必须要做的第一选择。

1.使用类似生产的本地数据库服务器进行集成测试

对于生产环境,我始终喜欢使用增量DDL脚本,因为我始终可以知道在给定服务器上部署了哪个版本,以及哪些是需要部署的较新脚本。 我一直依靠Flyway来为我管理模式更新,对此我非常满意。

在集成测试量很小的小型项目中,您也可以使用类似于生产的本地数据库服务器进行测试。 这是最安全的选择,因为它可以确保您在生产设置非常相似的环境中进行测试。

主要缺点是测试速度。 使用外部数据库意味着额外的时序成本,这很容易在大型项目中失控。 毕竟,谁喜欢每天运行60分钟的测试程序?

2.内存数据库集成测试

我选择使用内存数据库进行集成测试的原因是为了加快测试的运行时间。 这是一个影响测试运行时间的方面,还有许多其他方面可能会影响您,例如销毁和重新创建包含大量Bean依赖项的Spring应用程序上下文。

您可以选择许多内存数据库: HSQLDB , H2 , Apache Derby ,仅举几例。

我一直在使用两种内存中架构生成策略,它们都有优点和缺点,下面将对它们进行解释。

2.1利用hibernate.hbm2ddl.auto =” update”

Hibernate在配置它时非常灵活。 幸运的是,我们可以使用“ hibernate.hbm2ddl.auto” SessionFactory属性来自定义DDL生成。

部署架构的最简单方法是使用“更新”选项。 这对于测试目的很有用。 在生产环境中我不会依赖它,对于增量环境而言,增量DDL脚本是一种更好的方法。

因此,选择“更新”选项是Integration Testing架构管理的一种选择。

这就是我在Hibernate Facts代码示例中使用它的方式。

让我们从JPA配置开始,您可以在META-INF / persistence.xml文件中找到:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"xmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"><persistence-unit name="testPersistenceUnit" transaction-type="JTA"><provider>org.hibernate.ejb.HibernatePersistence</provider><exclude-unlisted-classes>false</exclude-unlisted-classes><properties><property name="hibernate.archive.autodetection"value="class, hbm"/><property name="hibernate.transaction.jta.platform"value="org.hibernate.service.jta.platform.internal.BitronixJtaPlatform" /><property name="hibernate.dialect"value="org.hibernate.dialect.HSQLDialect"/><em><property name="hibernate.hbm2ddl.auto"value="update"/></em><property name="hibernate.show_sql"value="true"/></properties></persistence-unit>
</persistence>

并且dataSource配置如下所示:

<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy"><constructor-arg><bean class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init"destroy-method="close"><property name="className" value="bitronix.tm.resource.jdbc.lrc.LrcXADataSource"/><property name="uniqueName" value="testDataSource"/><property name="minPoolSize" value="0"/><property name="maxPoolSize" value="5"/><property name="allowLocalTransactions" value="true" /><property name="driverProperties"><props><prop key="user">${jdbc.username}</prop><prop key="password">${jdbc.password}</prop><prop key="url">${jdbc.url}</prop><prop key="driverClassName">${jdbc.driverClassName}</prop></props></property></bean></constructor-arg></bean>

我认为Bitronix是我使用过的最可靠的工具之一。 在开发JEE应用程序时,我利用了使用中的Application Server提供的Transaction Manager。 对于基于Spring的项目,我必须雇用独立的事务管理器,在评估JOTM,Atomikos和Bitronix之后,我选择了Bitronix。 那是5年前,自从我部署并使用了几个应用程序以来。

即使应用程序当前仅使用一个数据源,我还是更喜欢使用XA Transactions。 我不必担心使用JTA会明显降低性能,因为当当前事务仅使用一个登记的数据源时,Bitronix使用1PC(单阶段提交) 。 由于最后一次资源提交的优化,它还可以添加多达一个非XA数据源。

使用JTA时,建议不要混合使用XA和本地事务,因为并非所有XA数据源都允许在本地事务中进行操作,因此我倾向于尽可能避免这种情况。

不幸的是,就像这种DDL生成方法一样简单,它有一个我不太喜欢的缺陷。 我不能禁用“ allowLocalTransactions”设置,因为Hibernate会创建DDL脚本并在XA事务之外对其进行更新。

另一个缺点是,您几乎无法控制Hibernate代表您部署的DDL脚本,并且在这种特定情况下,我不希望牺牲灵活性而不是方便性。

如果您不使用JTA并且不需要灵活决定将在当前数据库服务器上部署什么DDL模式,那么hibernate.hbm2ddl.auto =” update”可能是您的正确选择。

2.2灵活的架构部署

此方法包括两个步骤。 前者将使Hibernate生成DDL脚本,而后者将以自定义方式部署它们。

要生成DDL脚本,我必须使用以下Ant任务(即使正在通过Maven运行),这是因为在编写本文时,我没有可以使用的Hibernate 4 Maven插件:

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-antrun-plugin</artifactId><executions><execution><id>generate-test-sql-scripts</id><phase>generate-test-resources</phase><goals><goal>run</goal></goals><configuration><tasks><property name="maven_test_classpath" refid="maven.test.classpath"/><path id="hibernate_tools_path"><pathelement path="${maven_test_classpath}"/></path><property name="hibernate_tools_classpath" refid="hibernate_tools_path"/><taskdef name="hibernatetool"classname="org.hibernate.tool.ant.HibernateToolTask"/><mkdir dir="${project.build.directory}/test-classes/hsqldb"/><hibernatetool destdir="${project.build.directory}/test-classes/hsqldb"><classpath refid="hibernate_tools_path"/><jpaconfiguration persistenceunit="testPersistenceUnit"propertyfile="src/test/resources/META-INF/spring/jdbc.properties"/><hbm2ddl drop="false" create="true" export="false"outputfilename="create_db.sql"delimiter=";" format="true"/><hbm2ddl drop="true" create="false" export="false"outputfilename="drop_db.sql"delimiter=";" format="true"/></hibernatetool></tasks></configuration></execution></executions>...
</plugin>

有了“创建”和“删除” DDl脚本后,我们现在必须在Spring上下文启动时部署它们,这是使用以下定制Utility类完成的:

public class DatabaseScriptLifecycleHandler implements InitializingBean, DisposableBean {private final Resource[] initScripts;private final Resource[] destroyScripts;private JdbcTemplate jdbcTemplate;@Autowiredprivate TransactionTemplate transactionTemplate;private String sqlScriptEncoding = "UTF-8";private String commentPrefix = "--";private boolean continueOnError;private boolean ignoreFailedDrops;public DatabaseScriptLifecycleHandler(DataSource dataSource,Resource[] initScripts,Resource[] destroyScripts) {this.jdbcTemplate = new JdbcTemplate(dataSource);this.initScripts = initScripts;this.destroyScripts = destroyScripts;}public void afterPropertiesSet() throws Exception {initDatabase();}public void destroy() throws Exception {destroyDatabase();}public void initDatabase() {final ResourceDatabasePopulator resourceDatabasePopulator = createResourceDatabasePopulator();transactionTemplate.execute(new TransactionCallback<Void>() {@Overridepublic Void doInTransaction(TransactionStatus status) {jdbcTemplate.execute(new ConnectionCallback<Void>() {@Overridepublic Void doInConnection(Connection con) throws SQLException, DataAccessException {resourceDatabasePopulator.setScripts(getInitScripts());resourceDatabasePopulator.populate(con);return null;}});return null;}});}public void destroyDatabase() {final ResourceDatabasePopulator resourceDatabasePopulator = createResourceDatabasePopulator();transactionTemplate.execute(new TransactionCallback<Void>() {@Overridepublic Void doInTransaction(TransactionStatus status) {jdbcTemplate.execute(new ConnectionCallback<Void>() {@Overridepublic Void doInConnection(Connection con) throws SQLException, DataAccessException {resourceDatabasePopulator.setScripts(getDestroyScripts());resourceDatabasePopulator.populate(con);return null;}});return null;}});}protected ResourceDatabasePopulator createResourceDatabasePopulator() {ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();resourceDatabasePopulator.setCommentPrefix(getCommentPrefix());resourceDatabasePopulator.setContinueOnError(isContinueOnError());resourceDatabasePopulator.setIgnoreFailedDrops(isIgnoreFailedDrops());resourceDatabasePopulator.setSqlScriptEncoding(getSqlScriptEncoding());return resourceDatabasePopulator;}
}

配置为:

<bean id="databaseScriptLifecycleHandler" class="vladmihalcea.util.DatabaseScriptLifecycleHandler"depends-on="transactionManager"><constructor-arg name="dataSource" ref="dataSource"/><constructor-arg name="initScripts"><array><bean class="org.springframework.core.io.ClassPathResource"><constructor-arg value="hsqldb/create_db.sql"/></bean></array></constructor-arg><constructor-arg name="destroyScripts"><array><bean class="org.springframework.core.io.ClassPathResource"><constructor-arg value="hsqldb/drop_db.sql"/></bean></array></constructor-arg>
</bean>

这次我们可以摆脱任何本地交易,因此可以安全地设置:

<property name="allowLocalTransactions" value="false" />
  • 代码可在GitHub上获得 。

参考: Hibernate Fact:来自我们的JCG合作伙伴 Vlad Mihalcea的集成测试策略 ,位于Vlad Mihalcea的Blog博客上。

翻译自: https://www.javacodegeeks.com/2013/12/hibernate-facts-integration-testing-strategies.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/344778.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【渝粤教育】广东开放大学 插画与漫画 形成性考核 (27)

选择题 题目&#xff1a;先从整体开始绘制的一般顺序是 题目&#xff1a;正常头身比角色转化为Q版角色&#xff0c;基本可以用几个词说完&#xff0c;那就是 题目&#xff1a;影响衣服皱褶的的因素有 题目&#xff1a;关于女性漫画人物正面面部特征&#xff0c;以下说法正确的是…

蓝桥杯基础模块1:LED跑马灯

一、模块题目 二、原理简述 1、74HC138:三八译码器(3个输入,8个输出) 2、74HC573:锁存器(20个引脚,D1D8是数据输入端,Q1Q8是数据输出端&#

【渝粤教育】广东开放大学 文学概论 形成性考核 (31)

选择题 题目&#xff1a;对创作个性与文学风格这两个概念的关系理解正确的是&#xff08; &#xff09; 题目&#xff1a;审美意象总是以表达哲理和观念作为存在的目的和最高审美理想&#xff08; &#xff09; 题目&#xff1a;西方典型论发展的三个阶段是&#xff08; &#…

如何使用Hibernate将PostgreSQL枚举映射到JPA实体属性

介绍 开源的hibernate-types项目允许您映射JSON&#xff0c;ARRAY&#xff0c; YearMonth &#xff0c; Month或数据库特定的列&#xff08;例如INET地址&#xff09;。 在本文中&#xff0c;我们将看到使用JPA和Hibernate时如何将PostgreSQL Enum类型映射到Java数组。 Maven…

【渝粤教育】广东开放大学 物权法 形成性考核 (43)

选择题 题目&#xff1a;下列哪一选项不是民法上的物?&#xff08;&#xff09; 题目&#xff1a;甲有一套别墅&#xff0c;甲的下列何种行为不能体现物权的性质&#xff08;&#xff09; 题目&#xff1a;根据物权是否具有独立性不同&#xff0c;物权可以分为&#xff08;&am…

蓝桥杯基础模块2:蜂鸣器继电器

一、模块题目 二、原理简述 1、74HC138(参见模块1) 2、74HC02(参见模块1) 3、74HC573(参见模块1)

【渝粤教育】广东开放大学 管理会计 形成性考核 (33)

选择题 题目&#xff1a;固定成本和变动成本是根据成本按其( )分类的 答案&#xff1a;看左侧 题目&#xff1a;下列成本项目中&#xff0c; 属于变动成本的是 答案&#xff1a;看左侧 题目&#xff1a;企业某产品本月消耗各项费用如下:直接材料50000元&#xff0c;直接人工200…

蓝桥杯基础模块3_1:数码管静态显示

一、模块题目 二、原理简述 1、数码管 CT107D单片机综合实训平台上使用的数码管是F3461BH(倒数第二个字母是A则共阴,是B则共阳)。 F3461BH是一个4位8段的数码管,其中a、b、c、d、e、f、g、dp引脚分别对应8个段码,该8个引脚通过74HC573锁存器与单片机的P0端口相连。另外有…

【渝粤教育】广东开放大学 计算机导论 形成性考核 (51)

选择题 题目&#xff1a;Excel 2003所属的套装软件是______。 题目&#xff1a;下面说法正确的是&#xff08; &#xff09; 选择一项&#xff1a; a. 数据是加工之前的信息 b. 信息是数据加工的结果 c. 数据就是数字 d. 数据就是信息 题目&#xff1a;用流程图描述算法形象、直…

【渝粤教育】广东开放大学财务会计2 形成性考核 (34)

选择题 题目&#xff1a; 下列属于其他业务收入的是&#xff08;  &#xff09;。 选择一项&#xff1a; 答案&#xff1a;看左侧 题目&#xff1a; 下列各项中&#xff0c;应计入管理费用的是&#xff08;  &#xff09;。 选择一项&#xff1a; 答案&#xff1a;看左侧…

jersey客户端_项目学生:带有Jersey的Web服务客户端

jersey客户端这是Project Student的一部分。 其他职位包括带有Jersey的Webservice Client&#xff0c; 带有Spring Data的 业务层和持久性 。 RESTful Web应用程序洋葱的第一层是Web服务客户端。 它可以用于模仿包含AJAX内容的网页&#xff0c;也可以被webapp的编程用户用来模…

蓝桥杯基础模块3_2:数码管动态显示

一、模块题目 二、原理简述 动态显示的基本原理与实现思路(转载) 动态显示实质上就是轮流点亮单个数码管实现多位数码管整体显示的效果。在轮流显示过程中,每位数码管点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但…

【渝粤教育】电大中专中医基础知识 (2)作业 题库

1.下列表述中属于证的是 A.头痛 B.麻疹 C.风寒犯肺 D.恶寒 E.水痘 正确 正确答案&#xff1a;左边查询 学生答案&#xff1a;C 2.下列表述中属于症的是 A.水肿 B.消渴 C.咳嗽 D.肺痈 E.恶寒 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;未作答 3.“阳损及阴,阴损及…

Java:使用Toxiproxy模拟各种连接问题

用Toxiproxy和Java的HttpURLConnection模拟各种连接问题&#xff0c;以查看产生了什么样的错误&#xff1a;连接超时vs.读取超时vs.连接被拒绝…。 结果&#xff1a; 系统&#xff1a;openjdk 11.0.1 2018-10-16 (.setConnectTimeout 1) > java.net.SocketTimeoutExceptio…

蓝桥杯基础模块4_1:独立按键

一、模块题目 二、原理简述 1、独立按键的处理思路(转载) 一般情况下,独立按键有两个引脚,其中一个通过上拉电阻接到单片机的I/O端口,另外一端接地。也就是说,平时按键没有动作的时候,输出的是高电平,如果有按下动作发生,则输出的是低电平。那么,我们在程序设计的时…

【渝粤教育】广东开放大学 行政管理 形成性考核 (35)

选择题 题目&#xff1a; ( )是从行政过程的角度来看待行政职能的 选择一项&#xff1a; 答案&#xff1a;看左侧 题目&#xff1a; 经过1993年的机构改革&#xff0c;国务院机构减少到59个&#xff0c;其中部委40个&#xff0c;直属机构13个&#xff0c;办事机构5个和1个办公…

【渝粤教育】广东开放大学 Photoshop 图像处理 形成性考核 (24)

选择题 题目&#xff1a; 使用变换命令中的缩放命令时&#xff0c;按住哪个键可以保证等比例缩放&#xff1f;&#xff08; &#xff09; 答案&#xff1a;看左侧 题目&#xff1a; 将前景色和背景色恢复为默认颜色的快捷键是&#xff08;&#xff09;&#xff1f; 答案&#…

【渝粤教育】广东开放大学 个人与团队管理 形成性考核 (57)

选择题 题目&#xff1a;按照KOLB学习周期&#xff0c;一个完整的学习过程包含四个阶段&#xff0c;不属于这四个阶段的是&#xff08;&#xff09;。 答案&#xff1a;看左侧 题目&#xff1a; 小米的新工作需要录入大量文件&#xff0c;可他对打字不是很在行。他给自己制定了…

junit动态忽略测试_有条件忽略测试的JUnit规则

junit动态忽略测试我一直认为使用Ignore停用测试是一个坏主意。 例外&#xff0c;这可能是一种将间歇性失败的测试放入隔离区以供以后处理的方法&#xff08;如Martin Fowler 在此处所述 &#xff09;。 随着越来越多的测试不断被忽略和遗忘&#xff0c;这带来了测试套件衰减的…