在spring 4.1之前我們在準備測試資料時可能通過繼承abstracttransactionaljunit4springcontexttests,然後調用executesqlscript()進行測試,其中存在一個主要問題:如果要同時執行多個資料源的初始化就靠不住了,而且使用起來也不是特别便利,spring4.1提供了@sql注解來完成這個任務。
1、初始化spring配置:
<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
@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
@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注解即可。
@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()
也可以通過元注解把注解合并:
@retention(runtime)
@target(type)
@interface compositesqlgroup {
直接使用@compositesqlgroup注解即可。
5、事務
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