spring-mock + dbutil 用来测试数据库操作
大概流程:
1.用dbunit创建初始的测试数据。
2.用spring-mock 维护测试过程中的数据会滚,这样可以保证测试后数据库保持原状态。
3.用junit架构测试。
4.用dbunit销毁初始测试数据。
对Dao进行单元测试,一般有两种思路。一是Mock,对使用的底层API进行Mock,比如Hibernate和JDBC接口,判断接口有没有正确调用,另一种是实际访问数据库,判断数据库有没有正确读写。更多的情况下,我更倾向于后者,因为在使用ORM工具或者jdbcTemplate的情况下,dao一般只有简单的几行代码,没有复杂的逻辑,Mock测试一般没有什么意义,我们更关心的是,Hibernate mapping是否正确,ibatis sql是否正确等,所以实际读写数据库才能真正判断一个dao是否正确,这也是我们关心的测试内容。
package com.test.dbunit.dao;import javax.sql.DataSource;import org.dbunit.Assertion;import org.dbunit.database.DatabaseConnection;import org.dbunit.database.IDatabaseConnection;import org.dbunit.database.QueryDataSet;import org.dbunit.dataset.IDataSet;import org.dbunit.dataset.xml.FlatXmlDataSet;import org.dbunit.operation.DatabaseOperation;import org.junit.Assert;import org.junit.Before;import org.junit.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.io.ClassPathResource;import org.springframework.jdbc.datasource.DataSourceUtils;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;import org.springframework.test.context.transaction.TransactionConfiguration;import com.test.dbunit.entity.User;@ContextConfiguration(locations = { "classpath:testApplicationContext.xml" })@TransactionConfiguration(defaultRollback = true)public class UserDaoTest extends AbstractTransactionalJUnit4SpringContextTests {@Autowiredprivate UserDao userDao;@Autowiredprivate DataSource dataSource;private IDatabaseConnection conn;@Beforepublic void initDbunit() throws Exception {conn = new DatabaseConnection(DataSourceUtils.getConnection(dataSource));}@Testpublic void saveUser() throws Exception {User user = new User();user.setNick("user001");user.setPassword("password001");userDao.save(user);QueryDataSet actual = new QueryDataSet(conn);actual.addTable("user","select * from user where user.nick = 'user001'");IDataSet expected = new FlatXmlDataSet(new ClassPathResource("com/taobao/dbunit/dao/user001.xml").getFile());Assertion.assertEquals(expected, actual);}@Testpublic void updateUser() throws Exception {IDataSet origen = new FlatXmlDataSet(new ClassPathResource("com/taobao/dbunit/dao/user001.xml").getFile());DatabaseOperation.INSERT.execute(conn, origen);User user = new User();user.setNick("user001");user.setPassword("password002");userDao.update(user);QueryDataSet actual = new QueryDataSet(conn);actual.addTable("user","select * from user where user.nick = 'user001'");IDataSet expected = new FlatXmlDataSet(new ClassPathResource("com/taobao/dbunit/dao/user001_updated.xml").getFile());Assertion.assertEquals(expected, actual);}@Testpublic void removeUser() throws Exception {IDataSet origen = new FlatXmlDataSet(new ClassPathResource("com/taobao/dbunit/dao/user001.xml").getFile());DatabaseOperation.INSERT.execute(conn, origen);userDao.remove("user001");QueryDataSet actual = new QueryDataSet(conn);actual.addTable("user", "select * from user where nick = 'user001'");Assert.assertEquals(0, actual.getTable("user").getRowCount());}@Testpublic void findUser() throws Exception {IDataSet data = new FlatXmlDataSet(new ClassPathResource("com/taobao/dbunit/dao/user001.xml").getFile());DatabaseOperation.INSERT.execute(conn, data);User user = userDao.getUserByNick("user001");Assert.assertEquals("password001", user.getPassword());}}
package com.test.dbunit.dao.impl; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; import com.test.dbunit.dao.UserDao; import com.test.dbunit.entity.User; public class DefaultUserDao extends BaseDao implements UserDao { private static String QUERY_BY_NICK = "select * from user where user.nick = ?"; private static String REMOVE_USER = "delete from user where user.nick = ?"; private static String INSERT_USER = "insert into user(nick,password) values(?, ?)"; private static String UPDATE_USER = "update user set user.password = ? where user.nick = ?"; @Override public User getUserByNick(String nick) { return (User) getJdbcTemplate().queryForObject(QUERY_BY_NICK,new Object[]{nick}, new RowMapper(){ @Override public Object mapRow(ResultSet rs, int index) throws SQLException { User user = new User(); user.setNick(rs.getString("nick")); user.setPassword(rs.getString("password")); return user; } }); } @Override public void remove(String nick) { getJdbcTemplate().update(REMOVE_USER, new Object[]{nick}); } @Override public void save(User user) { getJdbcTemplate().update(INSERT_USER, new Object[]{user.getNick(), user.getPassword()}); } @Override public void update(User user) { getJdbcTemplate().update(UPDATE_USER, new Object[]{user.getPassword(), user.getNick()}); } }
1.<?xml version="1.0" encoding="UTF-8"?> 2.<dataset> 3. <user nick="user001" password="password001" /> 4.</dataset>
QueryDataSet actual = new QueryDataSet(conn); actual.addTable("user", "select * from user where user.nick = 'user001'"); IDataSet expected = new FlatXmlDataSet(new ClassPathResource( "com/taobao/dbunit/dao/user001_updated.xml").getFile()); Assertion.assertEquals(expected, actual);
@Test public void updateUser() throws Exception { setUpDataSet("com/taobao/dbunit/dao/user001.xml"); User user = new User(); user.setNick("user001"); user.setPassword("password002"); userDao.update(user); verifyDataSet("com/taobao/dbunit/dao/user001_updated.xml"); }