junit - 使用注释在 Spring junit 测试中注入(inject) sql 数据

标签 junit

我将 Junit 与 spring-test 一起使用,我想使用此注释进行经典的事务测试:

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

此数据将在同一事务中与 jdbcspring 模板一起注入(inject),并且这些数据将可用于 仅此测试。

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

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

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

最佳答案

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

首先创建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);
        }
    }
}

比在你的类(class)测试中添加:

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

技巧是如果您不添加监听器,则添加通常由 Spring 自动添加的所有监听器。避免这种情况会导致奇怪的错误。

这没有记录,但我发现如果没有带有事务性 Spring 测试的监听器,Spring 会自动添加这 3 个监听器(感谢 Debug模式!)

最后你可以给我们这个很酷的注释,如下所示:

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

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

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

关于junit - 使用注释在 Spring junit 测试中注入(inject) sql 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3263034/

相关文章:

junit - 使用 JUnit、Maven 和 Hudson/Jenkins 进行集成测试

java - 另一个 Ant + JUnit 类路径问题

java - 尝试为 dao hibernate 运行 Junit 测试会出现以下错误

java - 为什么我的代码会打印两次玩家姓名?

java - 如何处理 Hamcrest 匹配器的此错误

android - 如何在 Android Studio v0.5.2 中运行单独的测试方法

java - JUnit = 红条,即使我的assertEquals 是正确的

java - mockito test 在作为 junit test 运行时没有给出这样的方法错误,但是当在运行配置中手动添加 jar 时,它运行良好

java - JUnit 3 是否有类似于@Ignore 的东西

java - 如何通过 Junit 测试 Web Service 调用