在带有注释的Spring junit测试中注入sql数据

在带有注释的Spring junit测试中注入sql数据,junit,Junit,我将Junit与spring测试结合使用,我希望使用此注释进行经典的transactionnal测试: @Injectdata(“classpath:src/test/mydata.sql”) @试验 公共void myTest引发异常{ // ... } 这些数据将在同一事务中与jdbcspring模板一起注入&这些数据将可用于 只有这个测试 实际上,我是这样注入数据的: @测试 公共void myTest引发异常{ update(“我的sql查询”); } 我知道Unitils框架也做同

我将Junit与spring测试结合使用,我希望使用此注释进行经典的transactionnal测试:

@Injectdata(“classpath:src/test/mydata.sql”)
@试验
公共void myTest引发异常{
// ...
}
这些数据将在同一事务中与jdbcspring模板一起注入&这些数据将可用于 只有这个测试

实际上,我是这样注入数据的:

@测试
公共void myTest引发异常{
update(“我的sql查询”);
}

我知道Unitils框架也做同样的事情,但是使用的是数据集dbunit文件。

我自己创建了一个解决方案

首先创建Spring测试使用的侦听器:

公共类InjectDataTestExecutionListener扩展了DependencyInjectionTestExecutionListener{
私有静态JdbcTemplate JdbcTemplate;
私有静态数据源;
私有静态字符串编码=“UTF-8”;
@凌驾
/**
*通过l'annotation{@link SqlFileLocation}执行unéventuel脚本SQL indiqué
*先锋l'execution d'un测试。
*/
public void beforeTestMethod(TestContext TestContext)引发异常{
super.beforeTestClass(testContext);
方法MyMethdo=testContext.getTestMethod();
SqlFileLocation-dsLocation=MyMethdo.getAnnotation(SqlFileLocation.class);
if(dsLocation!=null){
executeSqlScript(testContext,dsLocation.value());
}
}
/**
*执行联合国脚本。
*@param testContext le context du test
*@param sqlResourcePath le chemin du fichier Sql
*@cas d'erreur d'accès au fichier中抛出数据访问异常
*/
私有void executeSqlScript(TestContext TestContext,字符串sqlResourcePath)引发DataAccessException{
JdbcTemplate JdbcTemplate=getJdbCTemplate(getDatasource(testContext));
Resource Resource=testContext.getApplicationContext().getResource(sqlResourcePath);
executeSqlScript(jdbcTemplate,新的EncodedResource(资源,编码));
}
私有数据源getDatasource(TestContext TestContext){
如果(数据源==null){
datasource=testContext.getApplicationContext().getBean(datasource.class);
}  
返回数据源;
}
私有JdbcTemplate getJdbCTemplate(数据源数据源){
if(jdbcTemplate==null){
jdbcTemplate=新的jdbcTemplate(数据源);
}  
返回jdbc模板;
}
/**
*通过un jdbcTemplate donné执行une资源。
*@将DataAccessException enc作为de pb d'acces au fichier抛出。
*/
私有静态void executeSqlScript(JdbcTemplate simpleJdbcTemplate,
EncodedResource)引发DataAccessException{
List语句=新建LinkedList();
试一试{
LineNumberReader lnr=新的LineNumberReader(resource.getReader());
String script=JdbcTestUtils.readScript(lnr);
字符分隔符=';';
如果(!JdbcTestUtils.containsSqlScriptDelimiters(脚本,分隔符)){
分隔符='\n';
}
splitSqlScript(脚本、分隔符、语句);
for(字符串语句:语句){
试一试{
simpleJdbcTemplate.update(语句);
}
捕获(DataAccessException ex){
掷骰子;
}
}
}
捕获(IOEX异常){
抛出新的DataAccessResourceFailureException(“不可能的d'ouvrir le script depuis”+资源,ex);
}
}
}
在您的课堂测试中添加:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(位置={/*…*/})
@事务性
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,DirtiesContextTestExecutionListener.class,TransactionalTestExecutionListener.class
,InjectDataTestExecutionListener.class
})
诀窍是,如果不添加侦听器,则添加通常由Spring自动添加的所有侦听器。避免导致奇怪的错误

这没有文档记录,但我发现如果没有带有transactionnal spring测试的侦听器,spring会自动添加这3个侦听器(感谢调试模式!)

最后你可以给我们这样一个很酷的注解:

@SqlFileLocation(“classpath:sql/myfil.sql”)
@试验
public void testGetAll()引发异常{/*…*/}
您甚至可以使用相对路径或绝对路径


很自然,插入将像其他插入一样在结尾自动回滚。

也许@Sql annotation可以做得更好。

添加足够的答案。