程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 持續集成之路——數據訪問層的單元測試(續)

持續集成之路——數據訪問層的單元測試(續)

編輯:C++入門知識

 三、使用DBUnit管理數據

        測試的維護一直是我比較頭疼的問題,期望可以有一個比較易於維護和可復用的方法來管理這些數據。在沒有更好的方法之前,暫時選用DBUnit。(反思:其實我一直在為沒有發生的事情擔心,使得事情根本沒有進展。從已存在的、最簡單的地方入手,才是正確的處理方式。)

        在pom.xml中引入dbunit和springtestdbunit包,後者提供通過注解方式使用DBUnit:


[html]

<dependency> 
    <groupId>org.dbunit</groupId> 
    <artifactId>dbunit</artifactId> 
    <version>2.4.9</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>com.github.springtestdbunit</groupId> 
    <artifactId>spring-test-dbunit</artifactId> 
    <version>1.0.1</version> 
    <scope>test</scope> 
</dependency> 

        <dependency>
            <groupId>org.dbunit</groupId>
            <artifactId>dbunit</artifactId>
            <version>2.4.9</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.springtestdbunit</groupId>
            <artifactId>spring-test-dbunit</artifactId>
            <version>1.0.1</version>
            <scope>test</scope>
        </dependency>

         DBUnit使用xml文件管理數據集,通過使用第三方的庫也可以很方便的支持JSON格式。這裡使用xml:


[html]

<?xml version="1.0" encoding="utf-8"?> 
<dataset> 
    <building id="1" name="SOHO"/> 
    <building id="2" name="New Gate Plaza"/> 
    <floor id="1" floor_num="2" building="1"/> 
    <floor id="2" floor_num="3" building="1"/> 
    <floor id="3" floor_num="5" building="2"/> 
</dataset> 

<?xml version="1.0" encoding="utf-8"?>
<dataset>
    <building id="1" name="SOHO"/>
    <building id="2" name="New Gate Plaza"/>
    <floor id="1" floor_num="2" building="1"/>
    <floor id="2" floor_num="3" building="1"/>
    <floor id="3" floor_num="5" building="2"/>
</dataset>
         這個數據文件放在了 /src/test/resources/中,與測試用例在同一個級別的目錄中。為了便於區分,我采用了:Dao類名-被測試的方法名-dataset.xml 的命名方式,例如:UserDao-findByname-dataxml.set。以後如果測試用例需要修改,就可以根據名字很方便地找到對應的數據集,並且不會影響其他測試用例。

         注意:

         1. 這裡的Element及其Attribute名稱要和數據庫的結構一一對應,而不是實體類。

         2. 如果同一個數據對象初始化時,需要初始化的字段數目不一樣,比如:一條數據需要初始化的字段是8個,而另外一個是4個。那麼一定要字段數多的放在前面。

 

         四、編寫測試用例

         在編寫用例前,還是看下被測試的代碼。用到的兩個實體類:


[java]

package com.noyaxe.myapp.entity; 
 
import javax.persistence.Entity; 
import javax.persistence.Table; 
 
@Entity 
@Table(name = "building") 
public class Building extends IdEntity { 
    private String name; 
 
 
    public String getName() { 
        return name; 
    } 
 
    public void setName(String name) { 
        this.name = name; 
    } 

package com.noyaxe.myapp.entity;

import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name = "building")
public class Building extends IdEntity {
    private String name;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

[java]

package com.noyaxe.myapp.entity; 
 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 
 
@Entity 
@Table(name = "floor") 
public class Floor extends IdEntity { 
    private Integer floorNum; 
    private Building building; 
 
    @Column(name = "floor_num") 
    public Integer getFloorNum() { 
        return floorNum; 
    } 
 
    public void setFloorNum(Integer floorNum) { 
        this.floorNum = floorNum; 
    } 
 
    @ManyToOne(optional = false) 
    @JoinColumn(name = "building") 
    public Building getBuilding() { 
        return building; 
    } 
 
    public void setBuilding(Building building) { 
        this.building = building; 
    } 

package com.noyaxe.myapp.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "floor")
public class Floor extends IdEntity {
    private Integer floorNum;
    private Building building;

    @Column(name = "floor_num")
    public Integer getFloorNum() {
        return floorNum;
    }

    public void setFloorNum(Integer floorNum) {
        this.floorNum = floorNum;
    }

    @ManyToOne(optional = false)
    @JoinColumn(name = "building")
    public Building getBuilding() {
        return building;
    }

    public void setBuilding(Building building) {
        this.building = building;
    }
}

        被測試的FloorDao:


[java]

package com.noyaxe.myapp.repository; 
 
import com.noyaxe.myapp.entity.Floor; 
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 
import org.springframework.data.repository.PagingAndSortingRepository; 
 
import java.util.List; 
 
public interface FloorDao extends JpaSpecificationExecutor<Floor>, PagingAndSortingRepository<Floor, Long> { 
    public Floor findByBuildingNameAndFloorNum(String building, Integer floorNum); 
 
    public List<Floor> findByBuildingName(String building); 

package com.noyaxe.myapp.repository;

import com.noyaxe.myapp.entity.Floor;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;

import java.util.List;

public interface FloorDao extends JpaSpecificationExecutor<Floor>, PagingAndSortingRepository<Floor, Long> {
    public Floor findByBuildingNameAndFloorNum(String building, Integer floorNum);

    public List<Floor> findByBuildingName(String building);
}

      測試用例也十分簡單:

     

[java]

package com.noyaxe.myapp.repository; 
 
import com.github.springtestdbunit.annotation.DatabaseSetup; 
import com.noyaxe.myapp.entity.Floor; 
import org.junit.Test; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; 
import org.springframework.test.context.support.DirtiesContextTestExecutionListener; 
 
import java.util.List; 
 
import static junit.framework.Assert.assertNull; 
import static org.junit.Assert.assertEquals; 
import static org.junit.Assert.assertNotNull; 
 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("classpath:applicationContext-test.xml") 
@TestExecutionListeners({ 
        DependencyInjectionTestExecutionListener.class, 
        DirtiesContextTestExecutionListener.class, 
        TransactionDbUnitTestExecutionListener.class}) 
public class FloorDaoTest { 
    @Autowired 
    private FloorDao floorDao; 
 
    @Test 
<PRE class=java name="code">    @DatabaseSetup("FloorDao-findbByBuidlingName-dataset.xml")</PRE>    public void testFindByBuildingName(){        List<Floor> singleFloorList = floorDao.findByBuildingName("SOHO");        assertEquals(1, singleFloorList.size());        List<Floor> twoFloorList = floorDao.findByBuildingName("New Gate Plaza");        assertEquals(2, twoFloorList.size());        List<Floor> emptyFloorList = floorDao.findByBuildingName("Test");        assertEquals(0, emptyFloorList.size());    }    @Test<BR><PRE class=java name="code">    @DatabaseSetup("FloorDao-findbByBuidlingNameAndFloorNum-dataset.xml")</PRE>    public void testFindByBuildingNameAndFloorNum(){        Floor floor = floorDao.findByBuildingNameAndFloorNum("SOHO", 2);        assertNotNull(floor);        Floor empty = floorDao.findByBuildingNameAndFloorNum("New Gate Plaza", 7);        assertNull(empty);        empty = floorDao.findByBuildingNameAndFloorNum("No Building", 7);        assertNull(empty);    }} 

package com.noyaxe.myapp.repository;

import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.noyaxe.myapp.entity.Floor;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;

import java.util.List;

import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-test.xml")
@TestExecutionListeners({
        DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionDbUnitTestExecutionListener.class})
public class FloorDaoTest {
    @Autowired
    private FloorDao floorDao;

    @Test
[java]
@DatabaseSetup("FloorDao-findbByBuidlingName-dataset.xml")      @DatabaseSetup("FloorDao-findbByBuidlingName-dataset.xml")    public void testFindByBuildingName(){        List<Floor> singleFloorList = floorDao.findByBuildingName("SOHO");        assertEquals(1, singleFloorList.size());        List<Floor> twoFloorList = floorDao.findByBuildingName("New Gate Plaza");        assertEquals(2, twoFloorList.size());        List<Floor> emptyFloorList = floorDao.findByBuildingName("Test");        assertEquals(0, emptyFloorList.size());    }    @Test[java] view plaincopyprint?@DatabaseSetup("FloorDao-findbByBuidlingNameAndFloorNum-dataset.xml")      @DatabaseSetup("FloorDao-findbByBuidlingNameAndFloorNum-dataset.xml")    public void testFindByBuildingNameAndFloorNum(){        Floor floor = floorDao.findByBuildingNameAndFloorNum("SOHO", 2);        assertNotNull(floor);        Floor empty = floorDao.findByBuildingNameAndFloorNum("New Gate Plaza", 7);        assertNull(empty);        empty = floorDao.findByBuildingNameAndFloorNum("No Building", 7);        assertNull(empty);    }}        通過代碼,可以很清楚的看到通過DatabaseSetup完成了對測試數據的引入。這裡在每個測試方法前引入不同的文件,如果所有的方法可以通過一個文件包括,那麼也可以在類前面使用DatabaseSetup引入數據文件。

        至此,一個完整的數據層測試用例已經呈現,並且可以運行。可是實際的過程卻並沒有這麼順利,接下來的文章就要總結一下遇到的問題。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved