DBUnit使用介紹

1、DbUnit設計理念
熟悉單元測試的開發人員都知道,在對數據庫進行單元測試時候,一般採用的方案有運用模擬對象(mock objects)和stubs兩種。經過隔離關聯的數據庫訪問類,好比JDBC的相關操做類,來達到對數據庫操做的模擬測試。然而某些特殊的系統,好比利 用了EJB的CMP(container-managed persistence)的系統,數據庫的訪問對象是在最底層並且很隱蔽的,那麼這兩種解決方案對這些系統就顯得力不從心了。
DBUnit的設計理念就是在測試以前,備份數據庫,而後給對象數據庫植入咱們須要的準備數據,最後,在測試完畢後,讀入備份數據庫,回溯到測試前的狀態;並且又由於DBUnit是對JUnit的一種擴展,開發人員能夠經過建立測試用例代碼,在這些測試用例的生命週期內來對數據庫的操做結果進行比較。java

2、DbUnit測試基本概念和流程
基於DbUnit 的測試的主要接口是IDataSet。IDataSet表明一個或多個表的數據。
能夠將數據庫模式的所有內容表示爲單個IDataSet 實例。這些表自己由Itable 實例來表示。
IDataSet 的實現有不少,每個都對應一個不一樣的數據源或加載機制。最經常使用的幾種 IDataSet實現爲:mysql

FlatXmlDataSet:數據的簡單平面文件 XML 表示 
QueryDataSet:用 SQL 查詢得到的數據 
DatabaseDataSet:數據庫表自己內容的一種表示 
XlsDataSet :數據的excel表示

DBUnit支持的數據庫包括,db2,h2,hsqldb,mckoi,mssql,mysql,netezza,oralce,postgresql.sql

3、DBUnit測試流程:數據庫

通常而言,使用DbUnit進行單元測試的流程以下: 1 根據業務,作好測試用的準備數據和預想結果數據,一般準備成xml格式文件。 2 在setUp()方法裏邊備份數據庫中的關聯表。 3 在setUp()方法裏邊讀入準備數據。 4 對測試類的對應測試方法進行實裝:執行對象方法,把數據庫的實際執行結果和預想結果進行比較。 5 在tearDown()方法裏邊,把數據庫還原到測試前狀態。

 4、實例開發:ide

一、新建一個pom工程,加入相關依賴:post

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.dbunit</groupId>
        <artifactId>dbunit</artifactId>
        <version>2.5.3</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-nop</artifactId>
        <version>1.7.24</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
    </dependency>

二、新建工程相關目錄單元測試

 

BaseDao.java文件:測試

public class BaseDao {
    private static Connection CONNECTION_INSTANCE = null;
    
    protected Connection getConnection() throws Exception{
        if(null==CONNECTION_INSTANCE){
            Class.forName("com.mysql.jdbc.Driver");
            CONNECTION_INSTANCE=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test","root","root");
        }
        return CONNECTION_INSTANCE;
    }
    
    protected void closeConnection() throws Exception{
        if(null!=CONNECTION_INSTANCE){
            if(!CONNECTION_INSTANCE.isClosed()){
                CONNECTION_INSTANCE.close();
            }
            CONNECTION_INSTANCE=null;
        }
    }
}

DBUnitUtils.java文件大數據

public class DBUnitUtils {
    
    //產生數據集
    public static void generateDatasetDtd(String[] tables) throws Exception{
        QueryDataSet dataSet=new QueryDataSet(DButils.getDataBaseConnection());
        for(String _table:tables){
            dataSet.addTable(_table);
        }
        FlatDtdDataSet.write(dataSet, new FileOutputStream(new File("resource/tmp.dtd")));
        //FlatXmlDataSet.write(dataSet,new FileOutputStream(new File("resource/dbunit1.xml")));  
    }
    
    //備份表數據
    public static void backupDatabase(String[] tables,File backupFile) throws Exception{
        QueryDataSet dataSet=new QueryDataSet(DButils.getDataBaseConnection());
        for(String _table:tables){
            dataSet.addTable(_table);
        }
        FlatXmlDataSet.write(dataSet, new FileOutputStream(backupFile));
    }
    
    //清空表數據,並導入測試數據
    public static void importTables(File dataFile) throws Exception{
        IDataSet dataSet=new FlatXmlDataSetBuilder().build(dataFile);
        DatabaseOperation.CLEAN_INSERT.execute(DButils.getDataBaseConnection(), dataSet);
    }
    
    //清空表數據,恢復備份數據
    public static void resumeDatabase(File backupFile) throws Exception{
        IDataSet dataSet=new FlatXmlDataSetBuilder().build(backupFile);
        DatabaseOperation.CLEAN_INSERT.execute(DButils.getDataBaseConnection(), dataSet);        
    }
}

DButils.java文件ui

public class DButils {
    private static IDatabaseConnection conn;
    
    //經過dbUnit建立數據庫鏈接
    public static IDatabaseConnection getDataBaseConnection() throws ClassNotFoundException, SQLException, DatabaseUnitException{
        if(conn==null){
            Class.forName("com.mysql.jdbc.Driver");
            Connection dbConn=DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
            conn =new MySqlConnection(dbConn,"test");
            return conn;
        }
        return conn;
    }
    
    //關閉數據庫鏈接
    public static void closeConnection(){
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        conn=null;
    }
    
}

User.java文件

public class User {    
    private long id;
    private String username;
    private String password;
    private String name;
    
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }   
}

UserService.java文件

public interface UserService {
    
    public long create(User user) throws Exception;
    
    public void update(User user) throws Exception;

    public User get(Long id) throws Exception;

    public void delete(Long id) throws Exception;

    public List<User> list() throws Exception;
}

UserServiceImpl.java文件

public class UserServiceImpl extends BaseDao implements UserService{

    //新增用戶返回主鍵
    public long create(User user) throws Exception {
        Long id=null;
        PreparedStatement stm=getConnection().prepareStatement("insert into user(username, password, name) values(?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
        stm.setString(1, user.getName());
        stm.setString(2, user.getPassword());
        stm.setString(3, user.getName());
        stm.executeUpdate();
        ResultSet rs=stm.getGeneratedKeys();
        if(rs.first()){
            id=rs.getLong(1);
        }
        return id;
    }

    //更新用戶
    public void update(User user) throws Exception {
        PreparedStatement stm = getConnection().prepareStatement("update user set password = ?, name = ? where username = ?", Statement.RETURN_GENERATED_KEYS);
        stm.setString(1, user.getPassword());
        stm.setString(2, user.getName());
        stm.setString(3, user.getUsername());
        stm.executeUpdate();
        closeConnection();
    }

    //獲取用戶
    public User get(Long id) throws Exception {
        User user = null;
        PreparedStatement stm = getConnection().prepareStatement("select username, password, name from user where id=?");
        stm.setLong(1, id);
        ResultSet rs = stm.executeQuery();
        if (rs.first()) {
            user = new User();
            user.setUsername(rs.getString(1));
            user.setPassword(rs.getString(2));
            user.setName(rs.getString(3));
            user.setId(id);
        }
        closeConnection();
        return user;
    }

    //刪除用戶
    public void delete(Long id) throws Exception {
        PreparedStatement stm = getConnection().prepareStatement("delete from user where id=?");
        stm.setLong(1, id);
        stm.executeUpdate();
        closeConnection();        
    }

    //返回全部用戶列表
    public List<User> list() throws Exception {
        List<User> users = new ArrayList<User>();
        PreparedStatement stm = getConnection().prepareStatement("select username, password, name, id from user");
        ResultSet rs = stm.executeQuery();
        while (rs.next()) {
            User user = new User();
            user.setUsername(rs.getString(1));
            user.setPassword(rs.getString(2));
            user.setName(rs.getString(3));
            user.setId(rs.getLong(4));
            users.add(user);
        }
        closeConnection();
        return users;
    }

}

UserServiceDBTestCase.java文件

public class UserServiceDBTestCase extends DatabaseTestCase{
    private UserService userService;
    
    @Override
    //新建一個userDao對象
    protected void setUp() throws Exception {
        super.setUp();
        userService = new UserServiceImpl();
    }

    @Override
    //清空userDao對象
    protected void tearDown() throws Exception {
        super.tearDown();
        userService = null;
    }

    @Override
    //獲取數據庫鏈接
    protected IDatabaseConnection getConnection() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
        return new MySqlConnection(conn, "test");
    }

    //獲取輸入數據流
    @Override
    protected IDataSet getDataSet() throws Exception {
        InputStream is = getClass().getResourceAsStream("/test-data.xml");
        return new FlatXmlDataSetBuilder().build(is);
    }
    
    //測試數據的建立
    public void testCreate() throws Exception{
        User user = new User();
        user.setName("testdata");
        user.setPassword("testPassword");
        user.setUsername("testAdmin");
        Long id = userService.create(user);
        
        assertNotNull(id);
        User dbUser =userService.get(id);
        assertNotNull(dbUser);
        assertEquals("testAdmin", dbUser.getUsername());
        assertEquals("testPassword", dbUser.getPassword());
        assertEquals("testAdministrator", dbUser.getName());
    }

    public void testGet() throws Exception{
        User user = userService.get(1L);
        assertNotNull(user);
        assertEquals("admin1", user.getUsername());
        assertEquals("123", user.getPassword());
        assertEquals("Administrator1", user.getName());
        
        User nullUser = userService.get(0L);
        assertNull(nullUser);
    }
    
    public void testDelete() throws Exception{
        User user = userService.get(1L);
        assertNotNull(user);
        
        userService.delete(1L);
        User nullUser = userService.get(1L);
        assertNull(nullUser);
    }
    
    public void testList() throws Exception{
        
        List<User> users = userService.list();
        assertNotNull(users);
        assertEquals(4, users.size());
    }
    
}

UserServiceTestCase.java文件

public class UserServiceTestCase extends TestCase{
    private UserService userService;    
    private File backupFile=new File("resource/backup-data.xml");
    
    @Override
    protected void setUp() throws Exception {
        userService=new UserServiceImpl();
    }
    
    @Before
    public void setUpData() throws Exception {
        //備份原來的數據
        DBUnitUtils.backupDatabase(new String []{"user"}, backupFile);
        //導入測試數據
        DBUnitUtils.importTables(new File("resource/test-data.xml"));
    }
    
    @After
    public void tearDownData() throws Exception{
        //恢復備份數據
        DBUnitUtils.resumeDatabase(backupFile);
        //關閉數據庫鏈接
        DButils.closeConnection();
    }
    
    public void testCreate() throws Exception{
        DBUnitUtils.importTables(new File("resource/test-data.xml"));
        User user = new User();
        DBUnitUtils.resumeDatabase(backupFile);
        DButils.closeConnection();
        user.setName("testdata");
        user.setPassword("testPassword");
        user.setUsername("testAdmin");
        Long id = userService.create(user);
        
        assertNotNull(id);
        User dbUser =userService.get(id);
        assertNotNull(dbUser);
        assertEquals("testAdmin", dbUser.getUsername());
        assertEquals("testPassword", dbUser.getPassword());
        assertEquals("testAdministrator", dbUser.getName());
    }

    public void testGet() throws Exception{
        User user = userService.get(1L);
        assertNotNull(user);
        assertEquals("admin1", user.getUsername());
        assertEquals("123", user.getPassword());
        assertEquals("Administrator1", user.getName());
        
        User nullUser = userService.get(0L);
        assertNull(nullUser);
    }
    
    public void testDelete() throws Exception{
        User user = userService.get(1L);
        assertNotNull(user);
        
        userService.delete(1L);
        User nullUser = userService.get(1L);
        assertNull(nullUser);
    }
    
    public void testList() throws Exception{        
        List<User> users = userService.list();
        assertNotNull(users);
        assertEquals(4, users.size());
    }
}

test-data.xml文件

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <user id="1" username="test-user1" password="test-user1" name="test-user1"/>
  <user id="2" username="test-user2" password="test-user2" name="test-user2"/>
</dataset>

接下來測試結果: 

demo代碼下載: dbunitDemo

總結:
使用了DBUnit後能夠實現了對數據庫的隔離,成功彌補了JUnit單元測試不清理數據現場的缺憾,實際上DBUnit只是簡單的在單元測試前把數據庫的數據進行了備份而後插入xml中配置好的數據,在測試結束後再用備份好的原數據庫數據填充回數據庫.但當面對複雜的表關係和大數據量的時候,每次進行測試都進行數據的備份,也是一個很大的負擔,並且把所有的測試數據都編寫在xml當中也是很大的工做量

相關文章
相關標籤/搜索