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

时间:2016-01-11 10:49:05

标签: spring spring-boot spring-batch spring-transactions spring-test

在我的春季启动项目中,有一个父春天云启动器 - 父母Bristxon-M4,我在集成测试中遇到了一个问题,当它添加到测试类时:

@ImportAutoConfiguration({BatchAutoConfiguration.class})

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

我观察的行为是当我尝试在另一个测试的@Entity方法中保存两个@ManyToOne(optional=false)关系的@Before个对象时,它会失败并显示以下消息:

  

尝试保存与未保存的瞬态实体具有非可空关联的一个或多个实体。在保存这些依赖实体之前,必须将未保存的瞬态实体保存在操作中。

我的设置如下:

应用程序的代码片段:

@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清理和迁移具有Spring Batch的repo表和表的模式。该服务在manuel测试下按预期工作,并且最初在运行MyRestServiceIT和CollectionBatchJobIT时,@SpringApplicationConfiguration类设置为MyServiceApplication并且已通过所有测试。

但是在我尝试优化测试执行时间并且更符合Spring Boot测试的最佳实践时,我正在减少加载的测试配置并使用新的@ImportAutoConfiguration和自定义TestConfiguration类而不是使用主SpringBootApplication类MyServiceApplication。 我已经成功地改进了我的其他集成测试,但是在完成CollectionBatchJobIT之后,My {{{{}}块中的MyRestServiceIT失败并出现了这个hibernate错误:

@Before

stacktrace显示保存调用实际上来自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 块。 调试时,entityA的保存操作显示缺少的ID,数据库不包含预期的行。

总结:将BatchAutoConfiguration添加到一个测试后,另一个测试失败,因为它不再将实体持久保存到底层数据库。

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

顺便说一下。如果从@Before行中省略了BatchAutoConfiguration,则CollectionBatchJobIT会因为没有提交到数据库而失败。

1 个答案:

答案 0 :(得分:0)

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

排除这些的一种方法是在假设您的测试配置类被相应命名的情况下,用以下内容替换@SpringBootApplication

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