在我的春季启动项目中,有一个父春天云启动器 - 父母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会因为没有提交到数据库而失败。
答案 0 :(得分:0)
您的问题可能源于以下事实:由于MyServiceApplication
注释启用了组件扫描,使用@SpringBootApplication
进行配置的测试会自动包含所有测试配置类。这很可能不是你想要的。
排除这些的一种方法是在假设您的测试配置类被相应命名的情况下,用以下内容替换@SpringBootApplication
:
@Configuration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = @Filter(type = FilterType.REGEX,
pattern = ".*TestConfiguration.*"))