尽管'DB_CLOSE_ON_EXIT = FALSE'

时间:2018-09-24 13:54:46

标签: java spring spring-boot junit h2

我有一些简短的单元测试,但由于以下原因而失败:

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和stacktrace。

2 个答案:

答案 0 :(得分:4)

仅使用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>

答案 1 :(得分:1)

我想您的各种单元测试类都用@RunWith(SpringJUnit4ClassRunner.class)进行了注释?

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

您可能还必须将surefire reuseForks参数设置为false,以防止JUnit在连续测试中重复使用相同的'context'。