你应该如何单元测试DAO层

若你所工作的项目使用到Spring、Hibernate、JPA,并且你想单元测试数据连接层(DAO),这篇文章可能帮到你。

当你打算测试DAO层,你需要连接数据库。但是你被不允许使用已有的数据库。原因可能有这两个,一是你有可能腐败将用来整合测试的数据,二是这数据其他开发组人员所专用的。

为了解决这问题,将用到内存数据库(in-memory database)。内存数据库是个不错选择。原因在于它测试完成后不留痕迹,且每次测试前都能保证数据库是空空的,没有任何表。

单元测试DAO

一个好的DAO测试应该保证数据库在测试前后状态一致。不留新添数据,回滚所有更新。

一、总要创建单元测试指定配置文件

这可以是创建DAO单元测试的第一步。这测试指定配置文件主要有用来测试的数据源信息,也就是用来连接内存数据库,覆盖主配置文件的数据源。譬如,主配置文件application-context.xml的数据源是MySQL,而测试指定配置文件application-context-test.xml的复用application-context.xml,除数据源需要另建为hsqldb内存数据库的外。

application-context-test.xml

<beans xmlns="http://www.springframework.org/schema/beans" ...>

	<import resource="application-context.xml" />

	<bean id="entityManagerFactoryBean"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" />

		<property name="packagesToScan" value="com.lun.entity" />

		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
		</property>
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.archive.autodetection">class,hbm</prop>
				<prop key="hibernate.hbm2ddl.auto">create</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
			</props>
		</property>
	</bean>

	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
		<property name="url" value="jdbc:hsqldb:mem:lun" />
		<property name="username" value="sa" />
		<property name="password" value="" />
	</bean>

</beans>

application-context.xml

<beans xmlns="http://www.springframework.org/schema/beans" ...>

	<context:component-scan base-package="com.lun" />

	<bean id="entityManagerFactoryBean"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" />

		<property name="packagesToScan" value="com.lun.entity" />

		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
		</property>
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.archive.autodetection">class,hbm</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
			</props>
		</property>
	</bean>

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url"
			value="jdbc:mysql://127.0.0.1:3306/learnspring?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC" />
		<property name="username" value="root" />
		<property name="password" value="123" />
	</bean>

	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactoryBean" />
	</bean>

	<tx:annotation-driven />

</beans>

二、编写DAO层单元测试

下例将用到Spring-test和Junit测试框架。

@ContextConfiguration(locations = "classpath:application-context-test.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class TestEmployeeDAO {

	@Autowired
	private EmployeeDAO employeeDAO;

	@Autowired
	private DepartmentDAO departmentDAO;

	@Rollback(true)
	@Transactional
	@Test
	public void testAddDepartment() {
		DepartmentEntity department = new DepartmentEntity("Information Technology");
		departmentDAO.addDepartment(department);

		List<DepartmentEntity> departments = departmentDAO.getAllDepartments();
		Assert.assertEquals(department.getName(), departments.get(0).getName());
	}

	@Test
	@Transactional
	@Rollback(true)
	public void testAddEmployee() {
		DepartmentEntity department = new DepartmentEntity("Human Resource");
		departmentDAO.addDepartment(department);

		EmployeeEntity employee = new EmployeeEntity();
		employee.setFirstName("Lokesh");
		employee.setLastName("Gupta");
		employee.setEmail("[email protected]");
		employee.setDepartment(department);

		employeeDAO.addEmployee(employee);

		List<DepartmentEntity> departments = departmentDAO.getAllDepartments();
		List<EmployeeEntity> employees = employeeDAO.getAllEmployees();

		Assert.assertEquals(1, departments.size());
		Assert.assertEquals(1, employees.size());

		Assert.assertEquals(department.getName(), departments.get(0).getName());
		Assert.assertEquals(employee.getEmail(), employees.get(0).getEmail());
	}
}

需要注意几点

1.开始测试前,加载测试指定配置文件。

@ContextConfiguration(locations = "classpath:application-context-test.xml")

2.加载配置文件后,就能轻易注入依赖。

@Autowired
private EmployeeDAO employeeDAO;

@Autowired
private DepartmentDAO departmentDAO;

3.使用@Rollback(true)注解还原数据库状态。

@Test
@Transactional
@Rollback(true)
public void testAddDepartment()
{
	//other code
}

4.每个测试都应创建一些数据,并验证这数据。重要的是,每一个测试用例都是独立的,它们不能有依赖关系。

三、项目结构

项目结构图

源码

引用

1.How you should unit test DAO layer

猜你喜欢

转载自my.oschina.net/jallenkwong/blog/1646774