2010-07-16 57 views
1

IM使用JUnit带弹簧的测试,我想有一个与此注释经典transactionnal测试:在Spring JUnit测试注入SQL数据与注释

@Injectdata("classpath:src/test/mydata.sql") 
@Test 
public void myTest throws Exception { 
    // ... 
} 

这些数据将与jdbcspring注入模板在同一个交易&这些数据将可用于 只有这个测试。

实际上,IM注射的数据是这样的:

@Test 
public void myTest throws Exception { 
    jdbcTemplate.update("my sql query); 
} 

我知道Unitils框架做samething但有数据集DbUnit的文件。

回答

3

我已经通过创建一个自己找到了解决方案。

首先创建由Spring测试中使用的监听器:

public class InjectDataTestExecutionListener extends DependencyInjectionTestExecutionListener { 

    private static JdbcTemplate jdbcTemplate; 
    private static DataSource datasource ; 
    private static String ENCODING="UTF-8"; 


    @Override 
    /** 
    * Execute un éventuel script SQL indiqué via l'annotation {@link SqlFileLocation} 
    * avant l'execution d'un test. 
    */ 
    public void beforeTestMethod(TestContext testContext) throws Exception { 
     super.beforeTestClass(testContext); 

     Method MyMethdo = testContext.getTestMethod(); 
     SqlFileLocation dsLocation = MyMethdo.getAnnotation(SqlFileLocation.class); 
     if (dsLocation!=null){ 
      executeSqlScript(testContext,dsLocation.value()); 
     } 
    } 

    /** 
    * Execute un script sur un chemin d'accès au fichier. 
    * @param testContext le context du test 
    * @param sqlResourcePath le chemin du fichier Sql 
    * @throws DataAccessException en cas d'erreur d'accès au fichier 
    */ 
    private void executeSqlScript(TestContext testContext, String sqlResourcePath) throws DataAccessException { 
     JdbcTemplate jdbcTemplate = getJdbCTemplate(getDatasource(testContext)); 
     Resource resource = testContext.getApplicationContext().getResource(sqlResourcePath); 
     executeSqlScript(jdbcTemplate, new EncodedResource(resource,ENCODING)); 
    } 

    private DataSource getDatasource(TestContext testContext) { 
     if (datasource==null){ 
      datasource = testContext.getApplicationContext().getBean(DataSource.class); 
     } 
     return datasource; 
    } 

    private JdbcTemplate getJdbCTemplate(DataSource datasource) { 
     if (jdbcTemplate==null){ 
      jdbcTemplate = new JdbcTemplate(datasource); 
     } 
     return jdbcTemplate; 
    } 

    /** 
    * Execute une resource via un jdbcTemplate donné. 
    * @throws DataAccessException enc as de pb d'acces au fichier. 
    */ 
    private static void executeSqlScript(JdbcTemplate simpleJdbcTemplate, 
      EncodedResource resource) throws DataAccessException { 

     List<String> statements = new LinkedList<String>(); 
     try { 
      LineNumberReader lnr = new LineNumberReader(resource.getReader()); 
      String script = JdbcTestUtils.readScript(lnr); 
      char delimiter = ';'; 
      if (!JdbcTestUtils.containsSqlScriptDelimiters(script, delimiter)) { 
       delimiter = '\n';   
      } 
      JdbcTestUtils.splitSqlScript(script, delimiter, statements); 
      for (String statement : statements) { 
       try { 
        simpleJdbcTemplate.update(statement); 
       } 
       catch (DataAccessException ex) { 
         throw ex; 
       } 
      } 
     } 
     catch (IOException ex) { 
      throw new DataAccessResourceFailureException("Impossible d'ouvrir le script depuis " + resource, ex); 
     } 
    } 
} 

比对你的类测试地址:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations={/* ... */}) 
@Transactionnal 
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,DirtiesContextTestExecutionListener.class,TransactionalTestExecutionListener.class 
    ,InjectDataTestExecutionListener.class  
}) 

TRICK是添加通常由Spring自动添加的所有听众如果你不添加监听器。避免导致奇怪的错误。

这不是证明,但香港专业教育学院发现,没有与transactionnal弹簧试验听者的3个听众由Spring自动添加

最后,你CAND我们这个凉爽的注释是这样的(由于调试模式!):

@SqlFileLocation("classpath:sql/myfil.sql") 
@Test 
public void testGetAll() throws Exception {/*...*/} 

你甚至可以使用相对路径或绝对路径。

自然插入将像其他人插入自动回滚结束。

0

也许@Sql注释可以做得更好。

+0

添加足够的答案。 – 2017-09-27 02:31:33