2010-07-16 4 views
1

im JUnit avec ressort test et je voudrais avoir un test Transactionnelle classique avec cette annotation:Injecter données SQL dans un test JUnit de printemps avec une annotation

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

Ces données seront injectées avec le jdbcspring modèle dans la même transaction & ces données seront disponibles pour seulement ce test.

En fait, im injecter des données de cette façon:

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

Je sais que le cadre Unitils faire samething mais avec un fichier DBUnit ensemble de données.

Répondre

3

J'ai trouvé la solution en en créant un moi-même.

d'abord créer l'auditeur utilisé par le test de printemps:

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); 
     } 
    } 
} 

que sur votre add test de classe:

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

Le TRICK était d'ajouter tous les auditeurs normalement ajoutés automatiquement par Spring si vous n'ajoutez pas d'écouteurs. Éviter que cela mène à des erreurs étranges.

Ce n'est pas documenté mais Ive a trouvé que, sans écoute avec un test de ressort Transactionnelle ces 3 auditeurs sont automatiquement ajoutés au printemps

Et enfin, vous nous cand cette annotation cool comme ça (merci le mode de débogage!):

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

Vous pouvez même utiliser des chemins relatifs ou un chemin absolu.

Et naturellement l'insertion sera comme d'autres inserts automatiquement rollback à la fin.

0

Peut-être que l'annotation @Sql peut le faire mieux.

+0

ajouter une réponse suffisante. –