原文:JPA implementation patterns: Testing
作者:Vincent Partington
出处:http://blog.xebia.com/2009/07/11/jpa-implementation-patterns-testing/
在JPA实施模式这一序列的前一篇文章中,我谈到了三种默认的使用JPA来映射继承层次体系的方式,并介绍了一种非标准的、但非常有用的方法,本周我则会讨论各种测试JPA代码的方法。
测试什么?
第一个要问的问题是:我们想要测试哪些代码?在谈论JPA的时候,我们涉及到了两类对象:领域对象和数据访问对象(DAO),从理论上讲,领域对象并不依赖JPA(它们是POJO,对吧?)因此,你可以在没有JPA提供程序(JPA provider)的情况下测试它们的功能,关于这方面,在这里没有什么值得一谈的。不过,在实践中,至少会使用JPA注释来注解领域对象,可能还会加入一些代码来管理(延迟的)双向关联、主键或者序列化的对象,这下子,事情变得更有趣了起来……
(即使这样的JPA特定代码违反了领域对象的POJO性质,但它是必需存在的,以便使得领域对象总是以相同的方式工作,无论是在JPA容器的内部还是外部,双向关联的管理以及使用UUID作为主键都是这一方面的很好的例子,在任何情况下,这都是最可肯定需要测试的代码。)
当然,我们还需要测试DAO,对吧?这里就立即出现了这样一个有趣的问题:我们为什么要测试DAO?它们中的大多数只不过是把工作委托给了JPA提供程序,而测试JPA提供程序显然没有什么意义,除非我们是在编写“学习用的测试”(亦见Robert Martin的干净的代码),或者是在开发自己的JPA提供程序。不过,DAO和领域对象的JPA特有部分之间的联合是应该要测试的。
测试的依据是什么?
既然知道要测试什么了,我们就可以决定依据什么来进行测试。由于是在测试数据库代码,所以我们会希望测试装置中包括一个数据库,该数据库可以是一个内置的内存数据库,如HSQLDB(仅使用内存模式)等,或者是一个“真正的”数据库,例如MySQL或者Oracle等。使用内置的数据库有一个很大的好处,那就是容易安装;不需要执行测试的每个人都运行一个MySQL或者Oracle的实例。不过,如果你的产品代码是运行在其他的数据库之上的话,那么通过这种方式你可能不能够捕捉到所有的数据库问题,因此,针对真正的数据库来进行集成测试还是需要的,但是更多的是在那之后再进行。
对于大多数的测试来说,我们需要的不仅仅是数据库,在测试之前,我们需要正确地设置它,在测试之后,则需要使它处在一种可用的状态中,以便于下一个测试的运行。在运行测试之前安装模式(schema)和使用正确的数据来填充数据库并不是那么难于做到(亦作为一个练习留给读者),不过,在测试之后使数据库返回到一个可用的状态则是一个较困难的问题,我找到了几种解决这一问题的方法:
Spring Framework框架包含了一个使用事务的测试框架来管理测试装置的状态,如果你使用了@Transactional来注释了测试的话,那么SpringJUnit4ClassRunner在每个测试开始之前会启动一个事务,并在测试结束时回滚该事务,返回到一个已知的状态。如果你仍在使用JUnit 3.8的话,你可以扩展AbstractTransactionalSpringContextTests这一基类以达到相同的效果,这看起来好像很不错,不过在实际中,我发现这一方法基于某些理由可以说是不够理想的:
1. 默认情况下,在事务被提交或者有查询被执行之前,JPA上下文都不会被刷新,因此,除非你的测试包括了查询,否则任何修改实际上都没有被传播到数据库中,而这可能会隐匿掉了无效映射等之类的问题。你可以在测试结束之前试着显式地调用EntityManager.flush,不过随后的测试就不再是代表了实际状况的了。
2. 此外,在同一个会话(session)中保存一个实体然后再检索它并不能够查出那些讨厌的延迟加载问题,在JPA提供程序将会返回一个到你刚保存的对象的引用的时候,你可能甚至连数据库都没有碰一下!
3. 最后要说的是,在测试中,你可能想先保存一些数据在数据库中,然后再运行测试,最后再检查正确的数据被写到了数据库中。为了测试这一过程,你可能需要三个单独事务,而且前面的两个事务不能被回滚。
如果使用内置的内存数据库的话,那么在运行第一个测试的时候,数据库是干净的,所以你不必担心在所有测试运行之后如何使之处在一个好的状态中,这就意味着你不需要回滚任何事务,并可以在一个测试中使用多个事务。不过你可能需要在测试与测试之间做一些特别的事情,例如,在使用Spring TestContext框架的时候,在上下两个测试之间,可以使用@DirtiesContext这一注解来重新初始化内存中的数据库。
如果不能够使用内存数据库,或者在每个测试之后都要重新初始化它的代价太昂贵的话,那么可以尝试在每个测试之后(或每个测试之前)都清除所有的表。例如,可以使用DbUnit来从测试表中删除所有的数据或是删去所有的测试表,不过外键约束有可能是个妨碍,所以在执行这些操作之前,你要暂时使参照完整性失效。
测试的范围是什么?
接下来的事情是确定测试的范围,不知你编写的是小的单元测试、较大的组件测试还是全面的集成测试?由于JPA的工作方式(可以说是它的抽象泄漏),一些问题可能只会在更大的范围中才表露出来,如果想了解基本的正确情况的话,虽然孤立地测试DAO的持久方法是有用的,但是需要在更大的范围之内进行测试,以便能够筛出那些有处理错误的延迟加载或者事务。要真正的测试系统的话,你需要通过较大的组件测试来组合小的单元测试,在这些组件测试中,把服务门面和DAO绑定测试。这两类测试都可以使用内存数据库来进行。要完全覆盖测试的范围的话,你需要以生产中使用的数据库来进行集成测试,可使用Fitnesse之类的工具,因为我们并没有专门在该种情况下测试JPA代码,所以规模较小的单元测试会较快地帮助你找出DAO的错误。
断言什么?
最后一件要解决的事情是在测试中断言什么?有可能是这样的情形,领域对象被映射到了现有的模式(schema)上,你想要确保这一具体情况中的映射是正确的,在这种情况下,你会想用原始的JDBC来访问底层的数据库来明确肯定正确的修改已经被写到正确的表中。不过,如果模式是由JPA映射来自动生成的话,那么你可能不会关心实际的模式。你想要明确肯定持久的对象能够在新的会话中内正确地检索出来,使用JDBC来直接地访问底层的模式是没有什么必要的,而且只会使得这样的测试代码变得脆弱。
很肯定在这篇博文中我并没有涵盖了所有的测试场景,因为测试数据库代码是一个非常复杂的领域,我很愿意知道你是如何测试数据库代码的,无论是使用JPA或者其他的一些持久性机制都可。
分享到:
相关推荐
**JPA(Java Persistence API)**是Java平台上的一个标准,用于管理关系数据库中的数据,它简化了数据库操作,提供了一种面向对象的方式来处理数据库事务。JPA通过ORM(Object-Relational Mapping)映射机制将Java...
Spring Data JPA 在 Spring Boot 项目中的集成与应用 Spring Data JPA 是一款基于 Java 持久层 API(JPA)的框架,提供了一个通用的数据访问层解决方案,能够简化 Java 应用程序中的数据访问工作。Spring Boot 作为...
一共有三个分卷。全部下载才能解压。 这本书不错,值得一看。
Spring Data JPA 是一个强大的框架,它简化了Java应用程序中对关系数据库的访问。在Spring Boot项目中,Spring Data JPA 提供了便捷的方式来进行数据持久化操作,减少了大量重复的DAO层代码。本篇文章主要关注Spring...
后来,尝试使用 Hibernate 或 JPA 等框架搜索具有相同值的列失败,因为搜索词没有填充到n ,导致搜索词与列中存储的值不匹配。 例如,考虑以下表定义: CREATE TABLE CITY ( ... NAME CHAR(40) NOT NULL ...);如果...
1:JPA: : 2:对象数据库: ://www.objectdb.com/ 3:JPA 性能基准: ://www.jpab.org/All/All/All.html 支持功能 支持所有蓝图功能, 除外 支撑 支持 支持 Java 5、6 或 7 支持 JPA 你需要哪一个取决于你想用...
本文将深入探讨JPA的测试用例设计和实施。 1. **基本概念理解** - JPA的核心是Entity(实体),对应数据库中的表。 - EntityManager是JPA的主要接口,负责管理实体对象的生命周期,包括创建、查找、更新和删除。 ...
Spring Data Jpa常用功能演示配套说明请查看:项目简介本项目采用当前最新版本的2.1.4.RELEASE做基础架构支撑,请参考本项目建议有一定的基础及经验。教程主要针对中文用户,如果您英文良好,建议直接阅读官网帮助...
【标题】"notes_JPA_JSF:使用JSF和JPA实施来重建Notes项目"涉及的是在Java开发环境中,利用JavaServer Faces (JSF) 和 Java Persistence API (JPA) 技术重构建一个名为Notes的项目。JSF是Java EE平台上的一个用户...
春天数据jpa额外使用jpa的spring数据更舒适我爱spring-data-jpa,她放开我的双手,粗鲁的方法很无聊! 然而,尽管她为我们提供了规范解决方案,但她在动态本机查询上并不完美,而且她的返回类型必须是一个实体,但是...
zdemo-jpa-base JPA测试示例集合
本文是介绍Spring-data-jpa的PPT的学习笔记,整理了Spring Data JPA相关知识配置和实践源码. 本文介绍知识点有: JPA与Spring的相关配置 JPA 方法名常用查询 JPA 使用@Query注解实现JPQL和本地自定义查询 JPA API 条件...
下面是 JPA 核心知识的讲解,包括 JPA 概述、JPA 入门、JPA 实体、JPA 实体管理器等。 JPA 概述 JPA 是什么?JPA 是 Java Persistence API 的缩写,全称为 Java 持久化 API。JPA 是一个 Java 标准,提供了一个通用...
由于其内存模式和易于使用的特性,它是与JPA集成的理想选择。在`application.properties`或`application.yml`中配置H2数据库连接: ```properties spring.datasource.url=jdbc:h2:mem:testdb spring.datasource....
该系列文章,以Spring作为技术主线,搭建个人网站,初步包含6篇文章,文章将逐步上线:Spring Boot Hello World : 如何使用Spring Boot构建web项目Spring MVC, JPA, H2数据库 : 模板技术,对象设计,JPA连接内存...
这些示例正在使用实现JPA规范的Hibernate供应商。 - jpa-sample-01: + Simple examples of CRUD in JPA + Demo QUERY and TYPEDQUERY + Configuration of JPA using Hibernate Provider - jpa-sample-02: + ...
spring-k8s-jpa-demo:了解如何将Spring Data JPA与Kubernetes结合使用
4. **测试验证**:迁移完成后,需要进行全面的测试以确保应用功能的一致性和正确性。 通过以上步骤,开发者可以顺利地将原有的Hibernate应用迁移到OpenJPA中,利用JPA提供的标准化API,提高代码的可移植性和可维护...