为什么 Spring Boot BatchAutoConfiguration 会阻止存储库在集成测试期间保存?

Why does Spring Boot BatchAutoConfiguration prevent repositories from saving during integration test?

在我的 spring 引导项目中,父项目 spring-cloud-starter-parent Bristxon-M4,我在将其添加到测试时遇到了集成测试问题 class:

@ImportAutoConfiguration({BatchAutoConfiguration.class})

我的问题是我不完全理解启动顺序以及加载配置的顺序 - 至少我怀疑这是我的问题。

我观察到的行为是,当我尝试在另一个测试的 @Before 方法中保存两个具有 @ManyToOne(optional=false) 关系的不同 @Entity 对象时,它失败了留言:

Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.

我的设置如下:

来自应用程序的代码片段:

@Configuration
@EnableBatchProcessing
public class CollectionBatchJobConfiguration ...

@SpringBootApplication
@EnableScheduling
@EnableJms
@EnableCircuitBreaker
public class MyServiceApplication
{
  public static void main(String[] args)
  {
     SpringApplication.run(MyServiceApplication.class, args);
  }
}

测试包中的代码片段:

@Configuration
@ImportAutoConfiguration({BatchAutoConfiguration.class, CollectionBatchJobConfiguration.class, RepositoryTestConfiguration.class})
public class CollectionBatchJobTestConfiguration
{
  @Autowired
  @Bean
  public JobLauncherTestUtils jobLauncherTestUtils()
  {
    return new JobLauncherTestUtils();
  }
...

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(CollectionBatchJobTestConfiguration.class)
public class CollectionBatchJobIT 
{
       @Autowired
       private JobLauncherTestUtils jobLauncherTestUtils;
...

@Configuration
@ImportAutoConfiguration({
    DataSourceAutoConfiguration.class,
    HibernateJpaAutoConfiguration.class,
    JpaRepositoriesAutoConfiguration.class,
    FlywayAutoConfiguration.class})
public class RepositoryTestConfiguration ...

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyServiceApplication.class)
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
@WebIntegrationTest
public class MyRestServiceIT
{
  @Autowired
  private EntityARepository entityARepo;
  @Autowired
  private EntityBRepository entityBRepo;

  @Before
  public void before()
  {
    EntityA a = new EntityA();
    a = entityARepo.save(a);
    EntityB b = new EntityB(a);
    entityBRepo.save(b); // This line fails with org.hibernate.TransientPropertyValueException 
  }
 ...

我在外部是 运行 MariaDB,并使用 Flyway 清理和迁移带有 repo 表和 Spring 批处理表的模式。该服务在手动测试下按预期工作,最初当 运行 MyRestServiceIT 和 CollectionBatchJobIT 与 @SpringApplicationConfiguration class 设置为 MyServiceApplication 运行 并通过所有测试时。

但在我尝试优化测试执行时间并更符合 Spring 引导测试最佳实践时,我正在精简加载的测试配置并使用新的 @ImportAutoConfiguration 与自定义 TestConfiguration classes 一起,而不是使用主 SpringBootApplication class MyServiceApplication。 我已经成功地改进了我的其他集成测试,但是在完成 CollectionBatchJobIT 之后,MyRestServiceIT 在 @Before 块中失败并出现此休眠错误:

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation :  
...  
Not-null property references a transient value - transient instance must be saved before current operation  

堆栈跟踪显示保存调用实际上来自 @Before 块。 调试时,entityA的保存操作显示缺少ID,数据库中没有预期的行。

综上所述:将BatchAutoConfiguration添加到一个测试后,另一个测试失败,因为它无法再将实体持久化到底层数据库。

任何人都可以解释发生了什么或者我如何找出背后的原因?

顺便说一句。如果 BatchAutoConfiguration 从 @ImportAutoConfiguration 行中省略,CollectionBatchJobIT 将失败,因为没有任何内容提交到数据库。

您的问题可能源于以下事实:由于 @SpringBootApplication 注释启用了组件扫描,因此使用 MyServiceApplication 进行配置的测试会自动包含所有测试配置 类 .这很可能不是您想要的。

排除这些的一种方法是将 @SpringBootApplication 替换为以下内容,前提是您的测试配置 类 已相应命名:

@Configuration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = @Filter(type = FilterType.REGEX,
                                        pattern = ".*TestConfiguration.*"))