为什么 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.*"))
在我的 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.*"))