天天看點

Spring4.1新特性——資料庫內建測試

在spring 4.1之前我們在準備測試資料時可能通過繼承abstracttransactionaljunit4springcontexttests,然後調用executesqlscript()進行測試,其中存在一個主要問題:如果要同時執行多個資料源的初始化就靠不住了,而且使用起來也不是特别便利,spring4.1提供了@sql注解來完成這個任務。

1、初始化spring配置: 

Spring4.1新特性——資料庫內建測試

<jdbc:embedded-database id="datasource1" type="hsql"/>  

<jdbc:embedded-database id="datasource2" type="hsql"/>  

<bean id="txmanager1" class="org.springframework.jdbc.datasource.datasourcetransactionmanager">  

    <property name="datasource" ref="datasource1"/>  

</bean>  

<bean id="txmanager2" class="org.springframework.jdbc.datasource.datasourcetransactionmanager">  

    <property name="datasource" ref="datasource2"/>  

此處使用jdbc:embedded嵌入資料庫來完成測試,資料庫使用hsql。

2、 方法級别的@sql

Spring4.1新特性——資料庫內建測試

@runwith(springjunit4classrunner.class)  

@fixmethodorder(methodsorters.name_ascending)  

@contextconfiguration(value = "classpath:spring-datasource.xml")  

@dirtiescontext(classmode = dirtiescontext.classmode.after_each_test_method)  

public class methodlevelsqltest {  

    private jdbctemplate jdbctemplate1;  

    private jdbctemplate jdbctemplate2;  

    @autowired  

    @qualifier("datasource1")  

    public void setdatasource1(datasource datasource1) {  

        this.jdbctemplate1 = new jdbctemplate(datasource1);  

    }  

    @qualifier("datasource2")  

    public void setdatasource2(datasource datasource2) {  

        this.jdbctemplate2 = new jdbctemplate(datasource2);  

    @test  

    @sql(value = {"classpath:schema.sql", "classpath:init-data.sql", "classpath:updated-data.sql"},  

            config =  

            @sqlconfig(encoding = "utf-8", separator = ";", commentprefix = "--",  

                    datasource = "datasource1", transactionmanager = "txmanager1"))  

    public void test01_simple() {  

        assert.assertequals(  

                integer.valueof(3),  

                jdbctemplate1.queryforobject("select count(1) from users", integer.class));  

    @sql(value = {"classpath:schema.sql", "classpath:init-data.sql"},  

                    datasource = "datasource2", transactionmanager = "txmanager2"))  

    public void test02_simple() {  

                integer.valueof(2),  

                jdbctemplate2.queryforobject("select count(1) from users", integer.class));  

}  

方法級别的@sql在每個方法上都會執行。其中@sql可以指定多個sql檔案,然後通過@sqlconfig指定其編碼、分隔符、注釋字首、使用哪個資料源和事務管理器。

3、類級别的@sql

Spring4.1新特性——資料庫內建測試

@sql(value = {"classpath:schema.sql", "classpath:init-data.sql", "classpath:updated-data.sql"},  

        config =  

        @sqlconfig(encoding = "utf-8", separator = ";", commentprefix = "--",  

                datasource = "datasource1", transactionmanager = "txmanager1"))  

public class classlevelsqltest {  

類級别的對整個測試用例中的每個方法都起作用。 

4、指定多個@sql 

java8之前需要使用@sqlgroup,而java8之後直接使用多個@sql注解即可。

Spring4.1新特性——資料庫內建測試

@transactional()  

@sqlgroup(  

        {  

                @sql(value = {"classpath:schema.sql", "classpath:init-data.sql", "classpath:updated-data.sql"},  

                        config =  

                        @sqlconfig(encoding = "utf-8", separator = ";", commentprefix = "--",  

                                datasource = "datasource1", transactionmanager = "txmanager1")),  

                @sql(value = {"classpath:schema.sql", "classpath:init-data.sql"},  

                                datasource = "datasource2", transactionmanager = "txmanager2"))  

        }  

)  

public class classlevelsqlgrouptest {  

    @transactional()  

也可以通過元注解把注解合并:

Spring4.1新特性——資料庫內建測試

@retention(runtime)  

@target(type)  

@interface compositesqlgroup {  

直接使用@compositesqlgroup注解即可。

5、事務

Spring4.1新特性——資料庫內建測試

public class transactionaltest {  

    @transactional("txmanager1")  

        //判斷是在事務中執行  

        assert.asserttrue(transactionsynchronizationmanager.isactualtransactionactive());  

        assert.asserttrue(testtransaction.isactive());  

    @transactional("txmanager2")  

    public void test03_simple() {  

        testtransaction.flagforrollback();  

    @rule  

    public testname testname = new testname();  

    @aftertransaction  

    public void aftertransaction() {  

        system.out.println(testname.getmethodname());  

        if("test03_simple".equals(testname.getmethodname())) {  

            assert.assertequals(  

                    integer.valueof(0),  

                    jdbctemplate2.queryforobject("select count(1) from users", integer.class));  

可以使用//判斷是在事務中執行transactionsynchronizationmanager.isactualtransactionactive()或testtransaction.isactive()來判斷是否是在事務中執行;通過testtransaction.flagforrollback();來復原事務;在測試用例中@aftertransaction來斷言復原後資料沒有插入。

本文轉自http://jinnianshilongnian.iteye.com/blog/2106184