【问题标题】:Spring configuration for embedded H2 database for tests用于测试的嵌入式 H2 数据库的 Spring 配置
【发布时间】:2011-01-02 00:11:37
【问题描述】:

使用 embedded h2 datasource 和可选的 JUnit 进行集成测试的 Spring 配置是什么样的?

我第一次尝试SingleConnectionDataSource 基本上成功了,但在需要同时连接多个连接或暂停事务的更复杂的测试中失败了。我认为tcp based server mode 中的 h2 可能也可以,但这可能不是内存中临时嵌入式数据库的最快通信模式。

有哪些可能性及其优点/缺点?另外,您如何创建表/填充数据库?


更新:让我们指定一些对此类测试很重要的具体要求。

  • 数据库应该是临时的并且在内存中
  • 出于速度要求,连接可能不应该使用 tcp
  • 如果我可以在调试期间使用数据库工具检查数据库的内容,那就太好了
  • 我们必须定义一个数据源,因为我们不能在单元测试中使用应用服务器数据源

【问题讨论】:

    标签: unit-testing spring embedded-database h2


    【解决方案1】:

    保留我不知道是否有任何工具可以检查数据库,我认为一个简单的解决方案是使用支持HSQL,H2的Spring嵌入式数据库(3.1.x docscurrent docs)和德比。

    使用 H2,您的 xml 配置将如下所示:

    <jdbc:embedded-database id="dataSource" type="H2">
        <jdbc:script location="classpath:db-schema.sql"/>
        <jdbc:script location="classpath:db-test-data.sql"/>
    </jdbc:embedded-database>
    

    如果您更喜欢基于 Java 的配置,您可以像这样实例化 DataSource(注意 EmbeddedDataBase 扩展了 DataSource):

    @Bean(destroyMethod = "shutdown")
    public EmbeddedDatabase dataSource() {
        return new EmbeddedDatabaseBuilder().
                setType(EmbeddedDatabaseType.H2).
                addScript("db-schema.sql").
                addScript("db-test-data.sql").
                build();
    }
    

    数据库表由 db-schema.sql 脚本创建,并由 db-test-data.sql 脚本中的测试数据填充。 p>

    不要忘记将 H2 数据库驱动程序添加到您的类路径中。

    【讨论】:

    • 如果数据库配置为从休眠 (hbm2ddl) 中的模型自动生成 DDL,则脚本在通过休眠生成数据结构之前运行。在 hbm2ddl 之后执行这些脚本有什么解决方案吗?
    【解决方案2】:

    我目前包含在一个仅用于测试的 springconfig 文件中作为数据源:

    <bean id="database.dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
        <constructor-arg>
            <bean class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
                <property name="driverClass" value="org.h2.Driver" />
                <property name="url"
                    value="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=2" />
            </bean>
        </constructor-arg>
    </bean>
    
    <!-- provides a H2 console to look into the db if necessary -->
    <bean id="org.h2.tools.Server-WebServer" class="org.h2.tools.Server" 
        factory-method="createWebServer" depends-on="database.dataSource" 
        init-method="start" lazy-init="false">
        <constructor-arg value="-web,-webPort,11111" />
    </bean>
    

    创建/删除表可以通过在覆盖AbstractAnnotationAwareTransactionalTests.onSetUpBeforeTransaction 时使用executeSqlScript 来完成,或者在适当的位置使用SimpleJdbcTestUtils.executeSqlScript

    也比较this posting

    【讨论】:

    • “我没有找到用 JUnit4 测试替代 executeSqlScript”尝试扩展 org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests
    • 感谢您的回答。在我添加 DB_CLOSE_DELAY 之前,我的单元测试在内存数据库中失败
    【解决方案3】:

    H2 与内置连接池实现捆绑在一起。以下 XML 提供了一个将其用作数据源 bean 的示例,无需引入对 DBCP 或 C3P0 的额外依赖项:

    <bean id="dataSource" class="org.h2.jdbcx.JdbcConnectionPool" destroy-method="dispose">
        <constructor-arg>
            <bean class="org.h2.jdbcx.JdbcDataSource">
                <property name="URL" value="jdbc:h2:dbname"/>
                <property name="user" value="user"/>
                <property name="password" value="password"/>
             </bean>
        </constructor-arg>
    </bean> 
    

    当 Spring 应用上下文关闭时,将通过调用 dispose 方法关闭数据库。

    【讨论】:

      【解决方案4】:

      我认为最好使用您的生产数据源实现(仅使用不同的连接字符串)进行单元测试。

      无论如何,“在更复杂的测试中失败”并没有提供足够的信息来提供更详细的答案。

      (自我广告:check this

      【讨论】:

      • 单元测试的生产数据库?如果你真的使用例如用于自动化测试的 oracle 数据库,例如一个maven构建你很容易遇到麻烦。这很慢,取决于那里的数据,没有其他人应该同时进行构建。 8-) 我更喜欢 oracle 模式下的 h2。顺便说一句:这个问题关于可用的可能性相当笼统,而不是关于我的具体问题。
      • 不,生产数据源实现。仅在连接字符串上有所不同
      • 啊,好的,但这将是应用程序服务器中的数据源。所以这是不可能的。
      • 哪一个是您在生产中使用的 DataSource 实现?
      • 是的,如果您希望将 TDD 作为 CI 流程的一部分,我认为这并不实用。也许您可以为一些辅助集成测试或负载测试执行此操作,但对于测试驱动的开发部分,如果您必须管理一个完整的数据库实例(如 MySQL)来运行,它会减慢测试的执行速度针对代码覆盖率的测试。总有一天我会错的,但现在我不会。
      猜你喜欢
      • 2016-09-07
      • 2017-03-01
      • 2012-10-22
      • 2018-06-13
      • 1970-01-01
      • 1970-01-01
      • 2017-10-23
      • 2012-01-21
      • 2017-03-05
      相关资源
      最近更新 更多