Spring Boot测试数据库初始化运行两次

时间:2019-07-12 16:00:23

标签: java spring hibernate spring-boot jpa

我正在测试Spring Boot Batch应用程序。我正在使用一个内存中的H2 DB,该数据库想通过一些数据进行初始化,但是以Unique index or primary key violation: PRIMARY_KEY_7 ON ...失败。

我尝试调整application.properties,添加和删除

spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.default_schema=AD1

还要调整spring.datasource.url

实体如下:

@Table(schema = "ad1",name = "Student")
public class Student {

    @Id
    @Column(name = "student_id")
    private String studentId;

    @Column(name = "student_name")
    private String studentName;

    @Column(name = "favourite_subject")
    private String favouriteSubject;

    @Column(name = "enrollment_date")
    private LocalDate enrollmentDate;

}

请注意,schema属性已设置为ad1

居住在data-h2.sql中的

src/test/resources如下:

Insert into ad1.Student (student_id,student_name,favourite_subject,enrollment_date) values ('1151AB26','John','Math',to_date('01-JAN-19','DD-MON-RR'));
同样在application.properties中的

src/test/resources如下:

spring.datasource.platform=h2
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=Oracle;INIT=CREATE SCHEMA IF NOT EXISTS AD1
spring.datasource.username=sa
spring.datasource.password=sa
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.properties.hibernate.default_schema=AD1
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

spring.batch.job.enabled=false

要注意的是spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=Oracle;INIT=CREATE SCHEMA IF NOT EXISTS AD1。我必须将架构初始化为AD1

我正在使用黄瓜,所以我有一个黄瓜测试班:

@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources", plugin = { "pretty", "html:target/cucumber" })
public class CucumberTest {

}

最后但并非最不重要的Spring Boot测试类

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = StudentBatchApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration
public abstract class SpringCucumberIntegrationTest {

发生的事情是,当我开始测试时,我得到以下信息:

Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_7 ON AD1.Student(student_id) VALUES ('1151AB26', 1)"; SQL statement:
Insert into AD1.Student (student_id,student_name,favourite_subject,enrollment_date) values ('1151AB26','John','Math',to_date('01-JAN-19','DD-MON-RR')) [23505-197]

当我对此进行故障排除时,通过在初始化发生时放置一个断点,该过程在同一行运行两次:

( /* key:1 */ '1151AB26', 'John', 'Math', TIMESTAMP '2019-01-01 00:00:00')
( /* key:2 */ '1151AB26', 'John', 'Math', TIMESTAMP '2019-01-01 00:00:00')

此后,它将引发异常。

1 个答案:

答案 0 :(得分:0)

正如我提到的,在故障排除过程中,我注意到data-h2.sql中的一行被以某种方式运行了两次,因此出现了唯一索引冲突。进一步进行故障排除,我追溯到该过程中加载数据脚本的位置(即data-h2.sql),并注意到它两次加载了此脚本。一次进入target\classes\data-h2.sql,一次进入target\test-classes\data-h2.sql。老实说,我不知道为什么将此脚本文件复制到target\classes\data-h2.sql

最后,我发现这是一个月食问题。当我使用命令行mvn clean test运行测试时。测试运行完美,但是当我使用Eclipse Run As -> JUnit Test运行测试时,我会遇到此问题。由于某种原因,每当我在Eclipse Project -> Clean中清理应用程序时,它都会将所有资源文件从src/main/resourcessrc/test/resources复制到target\classes中。我要做的是将以下行添加到我的.classpath文件中。

<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
    <attributes>
        <attribute name="maven.pomderived" value="true"/>
        <attribute name="test" value="true"/>
    </attributes>
</classpathentry>