【问题标题】:Inject sql data in a Spring junit test with an annotation在带有注释的 Spring junit 测试中注入 sql 数据
【发布时间】:2017-09-27 10:06:27
【问题描述】:

我将 Junit 与 spring-test 一起使用,我希望使用此注释进行经典的 transactionnal 测试:

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

此数据将在同一事务中与 jdbcspring 模板一起注入,这些数据将可用于 只有这个测试。

其实我是这样注入数据的:

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

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

【问题讨论】:

    标签: junit


    【解决方案1】:

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

    首先创建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 自动添加的侦听器,如果您不添加侦听器。避免这种情况会导致奇怪的错误。

    这没有记录,但我发现没有带有事务弹簧测试的侦听器,这 3 个侦听器是由 Spring 自动添加的(感谢调试模式!)

    最后你可以给我们这个很酷的注释:

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

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

    而且插入自然会像其他插入一样在最后自动回滚。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 添加足够的答案。
      猜你喜欢
      • 1970-01-01
      • 2019-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-30
      • 1970-01-01
      • 1970-01-01
      • 2018-05-15
      相关资源
      最近更新 更多