我有一些简短的单元测试,但由于以下原因而失败:
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。
答案 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'。