简体   繁体   English

如何防止在测试中违反参照完整性约束?

[英]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.

相关问题 H2参照完整性约束违反 - H2 Referential integrity constraint violation 尝试删除时违反参照完整性约束 - Referential integrity constraint violation when trying to delete 无继承关系的参照完整性约束违规 - Referential integrity constraint violation for none inheritance relationship 参照完整性约束违规 - 添加超过2条记录时失败 - Referential integrity constraint violation - failing when add more then 2 records 所有者删除时违反参照完整性约束(OneToMany单向) - Referential integrity constraint violation on owner delete (OneToMany unidirectional) Hibernate / H2 @OneToMany移除子代时违反“参照完整性约束”? - Hibernate/H2 @OneToMany “Referential integrity constraint violation” on remove of child? 更新和/或删除时违反 Hibernate H2 参照完整性约束 - Hibernate H2 Referential Integrity Constraint Violation on Update and/or Remove Spring 引导 - 测试存储库 - 违反参照完整性约束 - Spring Boot - testing repository - Referential integrity constraint violation 如何解决SQL完整性约束违规异常 - How to Solve SQL Integrity Constraint Violation Exception JPA 2:在保存具有无方向OneToMany关系的实体时违反了引用完整性约束 - JPA 2: Referential integrity constraint violation while saving entity with undirectional OneToMany relationship
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM