[英]How to prevent referential integrity constraint violation in tests?
I use JUnit 5 to create unit tests for my Spring Boot application.我使用 JUnit 5 为我的 Spring Boot 应用程序创建单元测试。
For each testing class, I use @Sql to load the context:对于每个测试类,我使用 @Sql 加载上下文:
HierarchyEntityServiceTest.java层次实体服务测试.java
@SpringBootTest
@ActiveProfiles("test")
@Sql({
"/sql/import_hierarchy_entity_type.sql",
"/sql/import_hierarchy_entity.sql",
"/sql/import_site_department.sql"
})
@Transactional
public class HierarchyEntityServiceTest {
@Autowired
private HierarchyEntityService hierarchyEntityService;
@Test
void findAllSkillCenters() {
assertThat(hierarchyEntityService.findAllSkillCenters())
.hasSize(5);
}
@Test
void findDepartmentsBySiteAndSkillCenter() {
assertThat(hierarchyEntityService.findDepartmentsBySitesAndSkillCenter(
List.of(11L),
"DPT_SWFC1"
)).hasSize(1);
}
}
SourceDetailsRepositoryTest.java SourceDetailsRepositoryTest.java
@SpringBootTest
@ActiveProfiles("test")
@Sql({
"/sql/import_hierarchy_entity_type.sql",
"/sql/import_hierarchy_entity.sql",
"/sql/import_source_details.sql",
"/sql/import_candidate.sql"
})
@Transactional
class SourceDetailsRepositoryTest {
@Autowired
private CandidateRepository candidateRepository;
@Autowired
private SourceDetailsRepository sourceDetailsRepository;
@Test
void findAllSourceDetailsTest() {
List<SourceDetails> sourceDetails = sourceDetailsRepository.findAll();
assertEquals(10, sourceDetails.size());
assertEquals("SOURCING", sourceDetails.get(0).getType());
}
@Test
void findSourceDetailsByTypeTest() {
List<SourceDetails> sourceDetails = sourceDetailsRepository.findByType("SOURCING");
assertEquals(7, sourceDetails.size());
}
@Test
void findSourceDetailByCandidateIdTest() {
Optional<Candidate> candidate = candidateRepository.findById(1000L);
Optional<SourceDetails> sourceDetails = sourceDetailsRepository.findById(candidate.get().getSourceDetailsId());
assertEquals(6L, sourceDetails.get().getId());
}
}
As you can see, some SQL scripts are called in multiple classes.如您所见,一些 SQL 脚本在多个类中被调用。
Those scripts all include data in the database:这些脚本都包含数据库中的数据:
import_hierarchy_entity.sql import_hierarchy_entity.sql
INSERT INTO public.hierarchy_entity(functional_code, label, short_label, type_functional_code,
parent_entity_functional_code)
VALUES ('CC_EDGE_EMB', 'CC Edge & Embedded', 'EE', 'CC', 'DIL'),
('DPT_AD1', 'AD1', 'AD1', 'DEPT', 'CC_AUG_DATA'),
('DPT_UE2', 'UE2', 'UE2', 'DEPT', 'CC_USER_EFF'),
('DPT_UE3', 'UE3', 'UE3', 'DEPT', 'CC_USER_EFF'),
('DPT_UE4', 'UE4', 'UE4', 'DEPT', 'CC_USER_EFF'),
('DPT_UE5', 'UE5', 'UE5', 'DEPT', 'CC_USER_EFF');
import_candidate.sql import_candidate.sql
INSERT INTO public.candidate(id, first_name, last_name, sex, status, author_id, manager_id, profile_id, site_id,
authored_at, edited_at, is_deleted, arrival_on, years_of_experience, source_id,
source_details, source_details_id, dept_code, entity_code)
VALUES (1000, 'JEAN', 'Louis', 'MALE', 'PREQUALIFICATION', 'admin', 'operationnel', 1, 2, CURRENT_TIMESTAMP(),
CURRENT_TIMESTAMP(), false, CURRENT_TIMESTAMP(), 1, 1, 'Viadeo', 6, 'DPT_EE1', 'CC_EDGE_EMB');
One thing to keep in mind, some tables have a functional_code, which is a string, as a primary key.要记住的一件事,有些表有一个功能码,它是一个字符串,作为主键。
Here is the configuration of the Spring Boot profile used for my tests:这是用于我的测试的 Spring Boot 配置文件的配置:
application.yml应用程序.yml
spring:
profiles: test
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
username: sa
password:
data:
classpath: import.sql
jpa:
database-platform: org.hibernate.dialect.H2Dialect
generate-ddl: true
hibernate:
default_schema: public
ddl-auto: create
show-sql: true
flyway:
enabled: false
When I run the tests individually, it works fine.当我单独运行测试时,它工作正常。 However, when I run the command
mvn test
, I get failures of the same kind:但是,当我运行命令
mvn test
,我遇到了相同类型的失败:
Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException:
Intégrité référentielle violation de contrainte: "FK87J5L5FKHUUWS58S4QUJU65O6: PUBLIC.CANDIDATE FOREIGN KEY(AUTHOR_ID) REFERENCES PUBLIC.MYREC_USER(ID) ('admin')"
Referential integrity constraint violation: "FK87J5L5FKHUUWS58S4QUJU65O6: PUBLIC.CANDIDATE FOREIGN KEY(AUTHOR_ID) REFERENCES PUBLIC.MYREC_USER(ID) ('admin')"; SQL statement:
INSERT INTO public.candidate(id, first_name, last_name, sex, status, author_id, manager_id, profile_id, site_id, authored_at, edited_at, is_deleted, arrival_on, years_of_experience, source_id, source_details, source_details_id, dept_code, entity_code) VALUES (1000, 'JEAN', 'Louis', 'MALE', 'PREQUALIFICATION', 'admin', 'operationnel', 1, 2, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP(), false, CURRENT_TIMESTAMP(), 1, 1, 'Viadeo', 6, 'DPT_EE1', 'CC_EDGE_EMB') [23506-200]
[ERROR] findAllSourceDetailsTest Time elapsed: 0.09 s <<< ERROR!
It seems the database isn't clean when a class tries to load the SQL scripts.当一个类尝试加载 SQL 脚本时,数据库似乎不干净。 Also, the file import.sql doesn't seem related to this, as it doesn't load the same data, and the issue persists when I remove it.
此外,文件import.sql似乎与此无关,因为它不加载相同的数据,并且当我删除它时问题仍然存在。
Isn't the context supposed to be cleaned before each testing class call?在每个测试类调用之前不应该清理上下文吗?
Is it possible to keep using the same scripts for multiple testing classes and avoid this situation?是否可以对多个测试类继续使用相同的脚本并避免这种情况?
Instead of the @Sql annotation, you can annotate your test class with the following.除了@Sql 批注,您还可以使用以下内容来批注您的测试类。 You can have the appropriate list of sql scripts for your respective test classes.
您可以为各自的测试类获得适当的 sql 脚本列表。
@SqlGroup({@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = {"classpath:schema.sql", "import_hierarchy_entity_type.sql", "import_hierarchy_entity.sql", "import_source_details.sql", "import_candidate.sql"})})
I have added schema.sql as an example in case you want to drop and recreate the schema after each test.我添加了 schema.sql 作为示例,以防您想在每次测试后删除并重新创建架构。 What the code will do is that it will execute the scripts before each test method.
代码要做的是在每个测试方法之前执行脚本。
NB: You can also replace @Transactional with @DataJpaTest for more JPA support.注意:您还可以将 @Transactional 替换为 @DataJpaTest 以获得更多 JPA 支持。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.