首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >构建过程中jUnit错误中的多个嵌入式HSQLDB数据库

构建过程中jUnit错误中的多个嵌入式HSQLDB数据库
EN

Stack Overflow用户
提问于 2015-01-26 20:05:21
回答 3查看 2.3K关注 0票数 2

我正在开发一个新的Spring批处理(3.0.3.RELEASE)应用程序,在这个应用程序中可以访问多个数据库。为了进行测试,我们使用HSQLDB (2.3.2)作为嵌入式数据库。

在我的应用程序上下文中,我有以下内容。

代码语言:javascript
复制
<jdbc:embedded-database id="dataSource">
</jdbc:embedded-database>

<jdbc:embedded-database id="proDataSource">
    <jdbc:script location="classpath:script-tables.sql" />
    <jdbc:script location="classpath:script-constraints.sql" />
</jdbc:embedded-database>

<jdbc:embedded-database id="altDataSource">
    <jdbc:script location="classpath:script-alt-tables.sql" />
</jdbc:embedded-database>

当我在Eclipse中运行一个测试时,一切都很好。当我从命令行构建时,在第一个测试之后,我会得到错误。

代码语言:javascript
复制
Failed to execute SQL script statement at line 3 of resource class path resource [script-promrkt-promo.sql]
object name already exists: PROMRKT

在我看来,EmbeddedDatabaseFactory中的人口进程正在接收一个已经填充的数据库。据我所知,每次测试之后,都不会执行关机,而且HSQLDB会将已经填充的数据库留在内存中。

我已经重新审查了文档,在弹簧医生中,这确实显示了一个显式的关机命令。但是,如果spring在我的测试开始时启动了嵌入式数据库,为什么它不在测试完成时关闭它呢?

  1. 对于相同的应用程序上下文,在每个单元测试之后,是否期望嵌入式数据库保持不变?
  2. spring启动嵌入式数据库的顺序是什么?事务上下文何时初始化?
  3. 我需要使用数据库清洁器吗?
  4. 是否可以将填充更新为只在数据库首次启动时填充,并在测试完成时回滚到原始脚本配置(有点像AbstractTransactionalSpringContextTests的工作方式)?
  5. 我需要一些交易标记吗?每个测试之间都正确地填充和销毁了Spring批处理的JobRepo。为什么我的定制dataSources没有?
EN

回答 3

Stack Overflow用户

发布于 2015-01-27 15:26:40

日志消息所抱怨的脚本不在您的配置中。我猜它是在别的地方被处决的吧?如果是这样的话,您可能需要将@DirtiesContext添加到您的测试中,这样Spring就不会缓存上下文(我假设您使用的是带有@ContextConfigurationSpringJunit4Runner,但是不能确定,因为您的实际测试不在问题中)。

如果我的假设是正确的,Spring会缓存上下文,以便在运行单元测试套件的过程中提高性能。如果您的测试以影响其他测试的方式修改上下文(比如在一个需要在其他测试中再次运行的测试中运行脚本),那么您可以使用@DirtiesContext标记测试,并且Spring不会缓存上下文。您可以在方法或类级别使用注释。您可以在这里阅读更多关于注释的内容:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/annotation/DirtiesContext.html

票数 3
EN

Stack Overflow用户

发布于 2015-01-29 16:30:47

我花了很多时间研究这个问题,并阅读了Spring文档(喘息!)并通过代码进行追踪。在4.1弹簧核中有一些有趣的变化,特别是测试。

我发现ApplicationContext(s)现在缓存在JVM级别。如果第二个测试请求一个上下文,TestContext首先在它的缓存中查找,以查看其他测试是否已经请求了相同的配置。

我有一些我的测试的简介。具有不同配置文件但相同的@ContextConfiguration的测试将导致应用配置文件重新加载该上下文。当"Bean“到达创建嵌入式数据库时,EmbeddedDatabaseFactory没有考虑到嵌入式数据库(内存中的HSQLDB)可能已经从以前的测试中创建或缓存,并且不需要重新初始化。

因此,我在EmbeddedDatabaseFactory.initDatabase()中添加了一些逻辑,在重新初始化和运行DatabasePopulator之前检查数据库是否已经存在。

代码语言:javascript
复制
    List existingDataBases = org.hsqldb.DatabaseManager.getDatabaseURIs();

    boolean isExisting = false;
    String localDBName = StringUtils.lowerCase(this.databaseName);

    for (Object object : existingDataBases) {
        if (object.toString().contains(localDBName)) {
            isExisting = true;
            break;
        }
    }

    // Now populate the database
    if (!isExisting && this.databasePopulator != null) {

(当然,这并不完全符合春天的需要,但它明白了问题的意义。)

在我看来,EmbeddedDatabaseFactory和TestContext缓存机制在一定程度上是个问题。我的"jdbc:embedded-database“定义没有任何与它们相关的配置文件。为什么缓存需要重新创建它们,而不是从现有的缓存bean中加载它们?

票数 1
EN

Stack Overflow用户

发布于 2016-02-24 19:35:45

每次创建新对象时,都可以使用generateUniqueName(true)设置惟一名称,从而强制创建新的嵌入式数据库。

下面是一个示例:

代码语言:javascript
复制
embeddedDatabase = new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .generateUniqueName(true)
            .addScripts("db/sql/create-db.sql", "db/sql/insert-data.sql")
            .build();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28157842

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档