I'll do my best to keep it very minimal.
This is the /scripts/exercises.sql file:
INSERT INTO exercises (id, name, description, difficulty) VALUES (10, 'Exercise 1', 'Description 1', 1);
INSERT INTO exercises (id, name, description, difficulty) VALUES (20, 'Exercise 2', 'Description 2', 2);
And the actual integration test:
@Sql(scripts = "/scripts/exercises.sql")
public class ExerciseIntegrationTest extends IntegrationTestSetup {
/** This test passes. */
@Test
public void getAll() {
client() // this comes from the base class
.when()
.get("/exercises")
.then()
.statusCode(200)
.body("size()", equalTo(2));
}
/** This test fails due to the primary key collision exception. */
/** This test could have even an empty body. */
@Test
public void getOne() {
client()
.when()
.get("/exercises/10")
.then()
.statusCode(200)
.body("id", equalTo(10))
.body("name", equalTo("Exercise 1"))
.body("description", equalTo("Description 1"))
.body("difficulty", equalTo(1));
}
The first test passes. The second test fails, because it tries to re-create the database, however it cannot re-create the database due to JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation (Primary Key collision).
The system has problems with re-creating the database between each test.
If I ran just the second test alone, then it would pass.
If I put the @Sql on the first test only, instead of on the class, then both test would succeed.
The error:
org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of class path resource [scripts/exercises.sql]: INSERT INTO exercises (id, name, description, difficulty) VALUES (10, 'Exercise 1', 'Description 1', 1); nested exception is org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Primary Key Violation (translated from non-english): "PRIMARY KEY ON PUBLIC.EXERCISES(ID) [10, 'Description 1', 1, 'Exercise 1']"
Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.EXERCISES(ID) [10, 'Description 1', 1, 'Exercise 1']"; SQL statement:
INSERT INTO exercises (id, name, description, difficulty) VALUES (10, 'Exercise 1', 'Description 1', 1) [23505-200]
Here is the base class:
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class IntegrationTestSetup {
@LocalServerPort
private int serverPort;
public RequestSpecification client() {
return RestAssured.given()
.basePath("/api/v1")
.port(serverPort)
.accept(MediaType.APPLICATION_JSON.toString())
.contentType(MediaType.APPLICATION_JSON.toString());
}
}
And here is the application-test.yml:
spring:
datasource:
url: jdbc:h2:mem:test_database;DB_CLOSE_DELAY=-1
username: sa
password:
driverClassName: org.h2.Driver
profiles:
active: test
Thanks for help.
P.S. I need to re-create the db between the tests, because the test may e.g. persist or remove entity.
Aucun commentaire:
Enregistrer un commentaire