lysu'''

          追求借鑒任何有益事物

          通過(guò)H2+Dbunit+JUnit進(jìn)行數(shù)據(jù)庫(kù)相關(guān)的測(cè)試

          很多時(shí)候我們?cè)诰帉?xiě)測(cè)試時(shí),常常需測(cè)試一些需要訪問(wèn)數(shù)據(jù)庫(kù)的功能,在處理這樣的測(cè)試時(shí),為了保證測(cè)試可模擬測(cè)試場(chǎng)景、可重復(fù)執(zhí)行,我們需要一個(gè)簡(jiǎn)單容易的數(shù)據(jù)準(zhǔn)備工具;一個(gè)隔離的干凈的數(shù)據(jù)庫(kù)環(huán)境。

          為了達(dá)到以上目標(biāo),可以通過(guò)許多方式達(dá)到,比如同事愛(ài)用的用各種Model的Builder+數(shù)據(jù)庫(kù)事務(wù)回滾(跨庫(kù)問(wèn)題),和有些人愛(ài)用的每次執(zhí)行前都清掉數(shù)據(jù)庫(kù)然后Dbunit(如果沒(méi)有自己獨(dú)立的庫(kù)往往影響其他同事工作)。

          最后自己選擇的方法是結(jié)合builder(準(zhǔn)備待插入數(shù)據(jù))和Dbunit,然后使用H2數(shù)據(jù)庫(kù)并開(kāi)啟內(nèi)存模式和MySQL兼容模式來(lái)處理與數(shù)據(jù)庫(kù)相關(guān)的測(cè)試。(是的,學(xué)習(xí)了Spring-Side的測(cè)試方法(*^__^*) ),這樣每次測(cè)試時(shí)都可以有個(gè)相當(dāng)干凈的環(huán)境,并且不需要為了跑個(gè)測(cè)試單獨(dú)建庫(kù)建表。

          對(duì)于Dbunit、H2的具體情況請(qǐng)查看相關(guān)文檔,這里就不做細(xì)述,下面就來(lái)看下如何結(jié)合H2\Dbunit進(jìn)行測(cè)試。

          首先,我們需要準(zhǔn)備H2數(shù)據(jù)庫(kù)。既然H2是“內(nèi)嵌式”數(shù)據(jù)庫(kù),自然不需傳統(tǒng)數(shù)據(jù)庫(kù)“安裝”過(guò)程,如果您使用maven,要做的僅僅是加入依賴包

          <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.3.160</version>
            <scope>test</scope>
          </dependency>

          就可以在代碼中直接連接h2并使用了。

          接下來(lái)要做的是并獲取他的數(shù)據(jù)源以進(jìn)行接下來(lái)的操作。

          這里根據(jù)項(xiàng)目使用的不通技術(shù)可以有不同選擇,比如項(xiàng)目使用了spring,那可以使用Spring Embedded database support(http://static.springsource.org/spring/docs/3.0.0.M4/spring-framework-reference/html/ch12s08.html

          <jdbc:embedded-database id="dataSource">
            <jdbc:script location="classpath:schema.sql"/>
            <jdbc:script location="classpath:test-data.sql"/>
          </jdbc:embedded-database>


          然后dataSource就被你所擁有…但這個(gè)在使用過(guò)程中發(fā)現(xiàn)個(gè)問(wèn)題就是通過(guò)使用embedded-database標(biāo)簽沒(méi)法自己定義連接URL開(kāi)啟MySQL模式,且因?yàn)轫?xiàng)目使用mybatis沒(méi)法像Hibernate之類的ORM容易處理sql語(yǔ)法不匹配問(wèn)題,最后沒(méi)有選擇使用。

          如需要通過(guò)使用spring管理配置數(shù)據(jù)源,可以考慮自己實(shí)現(xiàn)DataSourceFactoryBean,可以配置URL、用戶名、密碼和建表腳本路徑,然后在bean初始化時(shí)通過(guò)配置的建表語(yǔ)句建表…

          接下來(lái)要說(shuō)的是沒(méi)有使用spring的情況,這時(shí)使用老辦法,直接連接數(shù)據(jù)庫(kù)。

          public final class H2DatabaseUtil {
            private static final Logger logger = LoggerFactory.getLogger(H2DatabaseUtil.class);
            
          private
          H2DatabaseUtil() { }
          public static DataSource getDataSource() { if (logger.isDebugEnabled()) { logger.debug("get H2 data source."); } SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); dataSource.setDriverClass(org.h2.Driver.class); dataSource.setUsername("sa"); dataSource.setPassword(""); dataSource.setUrl("jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1"); return dataSource; }
          public static void initSchema(DataSource ds) { if (logger.isDebugEnabled()) { logger.debug("start init schema."); } try { QueryRunner queryRunner = new QueryRunner(ds); queryRunner.update("drop all objects"); if (logger.isDebugEnabled()) { logger.debug("delete all object k.o."); } try { queryRunner.update("runscript from '" + new DefaultResourceLoader() .getResource("schema.sql").getURL().toString() + "'"); if (logger.isDebugEnabled()) { logger.debug("rebuild the schema finish! f~resh meat..."); } } catch (IOException e) { logger.error(e.getMessage(), e); } } catch (SQLException e) { logger.error(e.getMessage(),e); } } }
          這里使用了DbUtils來(lái)簡(jiǎn)化建表語(yǔ)句的執(zhí)行,至于DataSource類型的選擇,可以根據(jù)情況自己更換。
          然后可以創(chuàng)建一個(gè)Test的基類讓測(cè)試代碼方便使用dataSource
          public abstract class AbstractDBAwareTestCase {
            protected QueryRunner queryRunner ;
            protected DataSource dataSource;
            
          protected
          void setUp() throws Exception { dataSource = getDataSource(); initSchema(dataSource); queryRunner = new QueryRunner(dataSource); } }
          之后寫(xiě)的單元測(cè)試只需繼承此類就可以獲取已建好庫(kù)的數(shù)據(jù)進(jìn)行測(cè)試。
          在得到數(shù)據(jù)源后,我們要做的操作是用Dbunit向這個(gè)嶄新的數(shù)據(jù)庫(kù)里頭灌入數(shù)據(jù)。
          覺(jué)得Dbunit還是不夠好用?這里推薦直接copy更改spring-side的Fixtures類
          http://springside.googlecode.com/svn/springside4/trunk/modules/core/src/main/java/org/springside/modules/test/data/Fixtures.java
          這個(gè)類有個(gè)問(wèn)題是需要對(duì)spring的resource相關(guān)類有依賴(獲取classpath下的文件之類的),如果有問(wèn)題還需更改下。
          最后看個(gè)簡(jiǎn)單Test的使用列子:
          public class AgentRepositoryTest extends AbstractDBAwareTestCase {
            private IAgentRepository agentRepository;
          
          @Before public void setUp() throws Exception { super.setUp(); reloadAllTable(dataSource, "/data/agent-data.xml"); agentRepository = Lookup.getDefault().lookup(IAgentRepository.class); }
          @Test public void should_find_agent_by_id() throws Exception { Agent agent = agentRepository.findById(dataSource, 1); assertNotNull(agent); assertThat(agent.getSimpleName(), is("demoa")); } }
          通過(guò)在setUp或測(cè)試開(kāi)始前reload\load數(shù)據(jù)就可以獲得所需的測(cè)試“場(chǎng)景”。
           
          能分享的就這些,如果還有其他好辦法歡迎交流!thx

          ps:還需要注意的是雖然使用H2的MySQL模式,但有的語(yǔ)句還是不兼容,比如建表語(yǔ)句中的comment\innodb\tinyint可能都需要稍作調(diào)整。

          posted on 2011-11-12 01:16 lysu 閱讀(4910) 評(píng)論(1)  編輯  收藏

          Feedback

          # re: 通過(guò)H2+Dbunit+JUnit進(jìn)行數(shù)據(jù)庫(kù)相關(guān)的測(cè)試 2011-11-13 14:48 淘寶特賣(mài)

          嗯,不錯(cuò)  回復(fù)  更多評(píng)論   



          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 无锡市| 和林格尔县| 句容市| 郎溪县| 奉新县| 丰台区| 任丘市| 聊城市| 奉化市| 肃宁县| 长沙县| 临安市| 镇原县| 彝良县| 固镇县| 仁怀市| 哈密市| 安康市| 新野县| 广丰县| 夏津县| 邮箱| 靖远县| 无极县| 三明市| 太保市| 河北区| 株洲市| 泸州市| 偏关县| 彭水| 济南市| 洛扎县| 赤城县| 成武县| 永善县| 镇沅| 外汇| 原阳县| 鹤山市| 拉孜县|