【问题标题】:H2 in-memory test DB closed, despite 'DB_CLOSE_ON_EXIT=FALSE' [duplicate]尽管'DB_CLOSE_ON_EXIT = FALSE',H2内存测试数据库已关闭[重复]
【发布时间】:2019-02-28 01:29:30
【问题描述】:

我有一些简短的单元测试失败,但有例外:

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement
::
Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement
::
Caused by: org.h2.jdbc.JdbcSQLException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-197]

来源是我的Spring Data AuditProvider,具体是这一行:

user = entityManager.createNamedQuery("findUserByUsernameAndTenant", User.class)
        .setParameter("tenant", TenantService.DEFAULT_TENANT_ID)
        .setParameter("username", UserService.USER_SYSTEM).getSingleResult();

错误在执行整个测试套件时发生,而不是仅在运行此测试类时发生。

这里是我正在使用的 TestRunner 等:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
@Rollback
public class MyTest {

这是我的数据源 URL:

spring.datasource.url: 'jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE'

看来“DB_CLOSE_ON_EXIT”并没有解决问题,知道这里发生了什么吗?

更新:

我刚刚意识到,只有在 Eclipse 中运行测试时才会发生这种情况,但它们是在命令行中运行的。虽然我偶尔会得到:

o.s.b.f.support.DisposableBeanAdapter    : Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL)

但我没有得到 PersistenceException 和堆栈跟踪。

【问题讨论】:

标签: java spring spring-boot junit h2


【解决方案1】:

仅使用DB_CLOSE_DELAY

对于内存数据库,你不应该使用DB_CLOSE_ON_EXIT=FALSE:你应该只使用DB_CLOSE_DELAY=-1。见http://www.h2database.com/html/features.html#in_memory_databases

所以你的数据源应该是:

spring.datasource.url: 'jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1'

您的单元测试也有可能在并行进程中执行。确保它们都在同一个 VM 中运行。

如果您使用 Maven,请将 forkCount 设置为 0

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.22.0</version>
  <configuration>
    <forkCount>0</forkCount>
  </configuration>
</plugin>

【讨论】:

  • 我根据您的建议对其进行了测试。我已经更改了连接字符串并添加了插件配置。它没有改变任何东西。我在命令行中运行了测试并且它们可以工作,请参阅上面的编辑。 :/ (为了澄清:无论是否使用 forkCount=0,它们都可以工作,并且在 Eclipse 中,它们总是被标记为异常失败)
  • @BenjaminMaurer 对不起。不幸的是,我不知道为什么 Eclipse 中的集成与通常的 Maven 构建如此不同。这主要是我使用 Netbeans 或 IntelliJ 的原因:它们与 Maven 或 Gradle 的集成要好得多。
  • @OlivierGrégoire 不应该使用DB_CLOSE_ON_EXIT=FALSE 是不正确的,请参阅the doc - 如果出于某种原因,您确实为嵌入式数据库配置了连接 U​​RL,请小心以确保禁用数据库的自动关闭。
【解决方案2】:

我猜你的各种单元测试类都用@RunWith(SpringJUnit4ClassRunner.class)注解了?

如果是这样,每个启动的测试类都会启动 Spring,而 Spring 又会启动 JPA。 如果 多个 测试类并行运行,每个测试类都创建然后删除 SAME 内存数据库,您可能会遇到一些并发问题。

您可能还必须将surefire reuseForks 参数设置为false,以防止JUnit 为连续 测试重复使用相同的“上下文”

【讨论】:

  • 抱歉,我补充了缺失的细节。该测试使用 SpringRunner,其中大部分都是,因为这些是我们的集成测试。
猜你喜欢
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 2012-12-12
  • 2014-12-20
  • 2020-05-13
  • 1970-01-01
相关资源
最近更新 更多