Spring Boot Test Database Initialization runs twice

Francisco :

I am testing a Spring Boot Batch Application. I am using a in memory H2 DB that I would like to initialize with some data but its failing with a Unique index or primary key violation: PRIMARY_KEY_7 ON ....

I have tried tweaking the application.properties, adding and removing

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

Also tweaking the spring.datasource.url.

The entity is as follows:

@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;

}

To note is that the schema attribute has been set to ad1

data-h2.sql which lives in src/test/resources is as follows:

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 also in src/test/resources is as follows:

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

To note, is that 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. I had to initialize the schema to AD1

I am using Cucumber so I have a a cucumber test class:

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

}

Last but not least the Spring boot test class

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

What happens is that when I start up the test I get the following:

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]

When I troubleshoot this, by putting a break-point at the moment the initialization is happening, the process runs the same line twice:

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

Right after this, it throws the exception.

Francisco :

As I mentioned, in the process of troubleshooting I noticed that the one line inside data-h2.sql was somehow being ran twice and hence giving this Unique index violation. Troubleshooting further, I traced back to the point in the process where it was loading the data script (ie. data-h2.sql) and noticed that it was loading this script twice. Once in target\classes\data-h2.sql and once in target\test-classes\data-h2.sql. I honestly don't know why this script file was being copied to target\classes\data-h2.sql.

In the end I found that this was an eclipse issue. When I ran the tests using command-line mvn clean test. The tests ran perfectly, but when I ran the tests with eclipse Run As -> JUnit Test I would encounter this problem. For some reason whenever I cleaned the application in eclipse Project -> Clean it copied all the resource files from src/main/resources and src/test/resources into target\classes. What I had to do was add the following line to my .classpath file.

<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>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=123658&siteId=1