Easy Integration Testing with Spring+Hibernate

原文地址:http://architects.dzone.com/articles/easy-integration-testing

 I am guilty of not writing integration testing (At least for database related transactions) up until now. So in order to eradicate the guilt i read up on how one can achieve this with minimal effort during the weekend. Came up with a small example depicting how to achieve this with ease using spring and hibernate. With integration testing, you can test your DAO(Data access object) layer without ever having to deploy the application. For me this is a huge plus since now i can even test my criteria's, named queries and the sort without having to run the application.

There is a property in hibernate that allows you to specify an sql script to run when the Session factory is initialized. With this, i can now populate tables with data that required by my DAO layer. The property is as follows;

<prop key="hibernate.hbm2ddl.import_files">import.sql</prop> 

According to the hibernate documentation, you can have many comma separated sql scripts.One gotcha here is that you cannot create tables using the script. Because the schema needs to be created first in order for the script to run. Even if you issue a create table statement within the script, this is ignored when executing the script as i saw it.

Let me first show you the DAO class i am going to test;

 package com.unittest.session.example1.dao;  
  
import org.springframework.transaction.annotation.Propagation;  
import org.springframework.transaction.annotation.Transactional;  
  
import com.unittest.session.example1.domain.Employee;  
  
@Transactional(propagation = Propagation.REQUIRED)  
public interface EmployeeDAO {  
  
 public Long createEmployee(Employee emp);  
   
 public Employee getEmployeeById(Long id);  

Nothing major, just a simple DAO with two methods where one is to persist and one is to retrieve. For me to test the retrieval method i need to populate the Employee table with some data. This is where the import sql script which was explained before comes into play. The import.sql file is as follows;

insert into Employee (empId,emp_name) values (1,'Emp test'); 

This is just a basic script in which i am inserting one record to the employee table. Note again here that the employee table should be created through the hibernate auto create DDL option in order for the sql script to run. More info can be found here. Also the import.sql script in my instance is within the classpath. This is required in order for it to be picked up to be executed when the Session factory is created.

Next up let us see how easy it is to run integration tests with Spring.

 package com.unittest.session.example1.dao.hibernate;  
  
import static org.junit.Assert.*;  
  
import org.junit.Test;  
import org.junit.runner.RunWith;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.test.context.ContextConfiguration;  
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
import org.springframework.test.context.transaction.TransactionConfiguration;  
  
import com.unittest.session.example1.dao.EmployeeDAO;  
import com.unittest.session.example1.domain.Employee;  
  
@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations="classpath:spring-context.xml")  
@TransactionConfiguration(defaultRollback=true,transactionManager="transactionManager")  
public class EmployeeHibernateDAOImplTest {  
  
 @Autowired  
 private EmployeeDAO employeeDAO;  

@Test  
 public void testGetEmployeeById() {  
  Employee emp = employeeDAO.getEmployeeById(1L);  
    
  assertNotNull(emp);  
 }  
   
 @Test  
 public void testCreateEmployee()  
 {  
  Employee emp = new Employee();  
  emp.setName("Emp123");  
  Long key = employeeDAO.createEmployee(emp);  
    
  assertEquals(2L, key.longValue());  
 }  
  

A few things to note here is that you need to instruct to run the test within a Spring context. We use theSpringJUnit4ClassRunner for this. Also the transction attribute is set to defaultRollback=true. Note that withMySQL, for this to work, your tables must have the InnoDB engine set as the MyISAM engine does not support transactions.

And finally i present the spring configuration which wires everything up;

 <?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"  
 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"  
 xsi:schemaLocation="    
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd    
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd    
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd    
          http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">  
  
  
 <context:component-scan base-package="com.unittest.session.example1" />  
 <context:annotation-config />  
  
 <tx:annotation-driven />  
  
 <bean id="sessionFactory"  
  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  <property name="packagesToScan">  
   <list>  
    <value>com.unittest.session.example1.**.*</value>  
   </list>  
  </property>  
  <property name="hibernateProperties">  
   <props>  
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
    <prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>  
    <prop key="hibernate.connection.url">jdbc:mysql://localhost:3306/hbmex1</prop>  
    <prop key="hibernate.connection.username">root</prop>  
    <prop key="hibernate.connection.password">password</prop>  
    <prop key="hibernate.show_sql">true</prop>  
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
    <!-- -->  
    <prop key="hibernate.hbm2ddl.auto">create</prop>  
    <prop key="hibernate.hbm2ddl.import_files">import.sql</prop>  
   </props>  
  </property>  
 </bean>  
  
 <bean id="empDAO"  
  class="com.unittest.session.example1.dao.hibernate.EmployeeHibernateDAOImpl">  
  <property name="sessionFactory" ref="sessionFactory" />  
 </bean>  
  
 <bean id="transactionManager"  
  class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  <property name="sessionFactory" ref="sessionFactory" />  
 </bean>  
  
</beans>  

That is about it. Personally i would much rather use a more light weight in-memory database such ashsqldb in order to run my integration tests.

Here is the eclipse project for anyone who would like to run the program and try it out.

时间: 2024-10-28 03:03:58

Easy Integration Testing with Spring+Hibernate的相关文章

JSF+Spring+Hibernate的实例讲解

js 使用JavaServer Faces(JSF).Spring Framework和Hibernate建立一个真实的Web应用程序内容概要使用JSF建立一个真实的Web应用程序不是没有意义的任务,这篇文章介绍了如何将JSF与Sping Framework和Hibernate集成,并且给出了使用这些技术建立这个真实的Web应用程序的最佳实践和设计指导 JavaServer Faces(JSF)技术是J2EE应用程序的一个新的用户接口框架,它非常适合基于MVC(Model-View-Contro

java-关于spring+hibernate 注入sessionFactory为null的问题

问题描述 关于spring+hibernate 注入sessionFactory为null的问题 最近一个项目需要用到struts2+spring+hibernate组合框架,我在一点一点的做配置,但做到注入SessionFactory时,一直不成功,在网上搜的一些解决方案也都不适用.故在此发布,希望高手们不吝赐教.web.xml的配置为: <?xml version=""1.0"" encoding=""UTF-8""

Struts+Spring+Hibernate实现上传下载

上传|下载 引言 文件的上传和下载在J2EE编程已经是一个非常古老的话题了,也许您马上就能掰着指头数出好几个著名的大件:如SmartUpload.Apache的FileUpload.但如果您的项目是构建在Struts+Spring+Hibernate(以下称SSH)框架上的,这些大件就显得笨重而沧桑了,SSH提供了一个简捷方便的文件上传下载的方案,我们只需要通过一些配置并辅以少量的代码就可以完好解决这个问题了. 本文将围绕SSH文件上传下载的主题,向您详细讲述如何开发基于SSH的Web程序.SS

浅谈如何结合JDBC事务与Spring+Hibernate

问题:客户在其数据库操作过程中需要调用我们的工作流接口,这样就需要将我们的工作流操作与他 们的业 务操作置于同一个事务中.我们的服务采用的都是spring的声明式事务,而客户采用的是对 connection进行事务处理. 如何保证JDBC事务的一致性? 想到的解决方案一:使用jta事务,用tomcat+jotm提供事务管理器.为什么一开始就想到要使用jta事 务??实际上我们和客户都是使用的同一个数据库,为了方便,各自使用了不同的数据库连接方式,使用 jta的话确实有bt的意思在里面.但是事实上

spring+hibernate避免延迟加载异常

在hibernate中,延迟加载是1个非常大的优点,但有时候却给我们带来一些小麻烦,在后台查询结束后,session已经关闭,但在前台显示的时候,如果存在关联关系就会产生延迟加载异常. 解决办法是客户端每次请求就分配1个session,将请求结果返回给客户端,并完成展现后关闭session. 实现这个功能非常简单,在web.xml中加入以下配置 <filter> <filter-name>hibernateFilter</filter-name> <filter-

Spring+Hibernate乱码解决方案

今天用spring+hibernate进行中文插入时出现乱码问题,通过查资料和自己反复测试终于解决了. 总结了两种方法: 1.使用gb2312编码,变更mysql的数据库编码字符集.cmd模式下用mysql --default-character-set=gb2312 -u root -p进入,然后再每个建表语句后增加default character set gb2312; 重新建立数据表. 值得注意的地方是:applicationContext.xml中的数据库连接必须设置为<propert

springmvc-请教:Spring + Hibernate 无法将数据写入数据库?

问题描述 请教:Spring + Hibernate 无法将数据写入数据库? Spring + Hibernate 无法将数据写入数据 请教: 通过Junit单元测试Service可以将数据写入数据库:但部署访问却无法向数据库写入数据. 1 环境: Spring 3.1.2 Hibernate 4.1.4 Jdk1.6 2 配置: 2.1 Web.xml <!-- Spring ApplicationContext配置文件的路径,可使用通配符,多个路径用,号分隔 此参数用于后面的Spring C

spring hibernate jpa 用findAll的时候,取出的所有的string类型的字段都是空字符串

问题描述 spring hibernate jpa 用findAll的时候,取出的所有的string类型的字段都是空字符串 但数据库中是有值的,int值可以选出{""id"":18187no"":""""parent_id"":11654name"":""""route"":"""

spring hibernate 动态数据源 同步所有库的表结构问题

问题描述 spring hibernate 动态数据源 同步所有库的表结构问题 采取spring + hibernate 组成动态多数据源(每个库的表结构相同). 现程序升级需要对数据库表结构进行更改,将hibernate 的hibernate.hbm2ddl.auto 配置为update,结果只能修改defaultTargetDataSource 所连接的一个库. 求有可以使hibernate.hbm2ddl.auto 自动更新所有的库解决方案. 补充:是一个sessionFactory(or