2010-07-16 81 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