Spring 如果@Transactional
我有一个简单的Spring引导应用程序,它使用Spring数据JDBC存储库并公开RESTAPI。除了我的集成测试之外,一切都正常运行。请参阅下面的存储库配置摘录Spring 如果@Transactional,spring,spring-boot,spring-data,spring-boot-test,spring-data-jdbc,Spring,Spring Boot,Spring Data,Spring Boot Test,Spring Data Jdbc,我有一个简单的Spring引导应用程序,它使用Spring数据JDBC存储库并公开RESTAPI。除了我的集成测试之外,一切都正常运行。请参阅下面的存储库配置摘录 @Configuration @EnableJdbcRepositories class RepositoryConfig : AbstractJdbcConfiguration() { @Bean @Profile("int-test") fun intTestDataSource():
@Configuration
@EnableJdbcRepositories
class RepositoryConfig : AbstractJdbcConfiguration() {
@Bean
@Profile("int-test")
fun intTestDataSource(): DataSource {
return EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("sql/h2/schema_create.sql")
.build()
}
@Bean
fun namedParameterJdbcOperations(dataSource: DataSource): NamedParameterJdbcOperations {
return NamedParameterJdbcTemplate(dataSource)
}
@Bean
fun transactionManager(dataSource: DataSource): TransactionManager {
return DataSourceTransactionManager(dataSource)
}
}
集成测试如下
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@ActiveProfiles("int-test")
@Transactional
class OrganizationControllerIntTest {
@Autowired
private lateinit var organizationRepository: OrganizationRepository
@Autowired
private lateinit var restTemplate: TestRestTemplate
@Autowired
private lateinit var testDataGenerator: TestDataGenerator
@BeforeEach
fun beforeEach() {
val organizations = testDataGenerator.organizations(10).toList()
organizationRepository.saveAll(organizations)
}
@Test
fun `When GET organizations then return all organizations`() {
val result = restTemplate.getForEntity("/organizations", String::class.java)
assertThat(result?.statusCode, equalTo(HttpStatus.OK))
assertThat(result?.body, containsString("items"))
}
}
如果未应用
@Transactional
注释,则测试成功。因为我需要在每次测试后回滚更改,所以我希望使测试具有事务性。问题是,在这种情况下,响应不包含任何项,例如数据库将为空,我无法找出原因。使用带有系统测试的@Transactional
将无法工作
发生的情况是在每个方法插入数据库之前,@中的数据但是事务从未提交。数据仅在同一事务中可见
现在,您向服务器发送一个HTTP请求,服务器将打开到数据库的新连接并启动一个新事务。但是,由于来自另一个事务的数据没有提交,因此它不会看到任何内容
@Transactionl
仅在使用MockMvc
时有效,因为它将在同一事务和线程中运行。实际发出HTTP请求时,情况并非如此
为每个测试使用数据设置,但在进行完整系统测试时应谨慎!你可以:
如果您真的想要进行系统测试,那么以一种无所谓的方式编写测试
使用MockMvc
运行测试,而不是实际的HTTP请求,这将使它(重新)使用相同的事务
不要编写系统测试,而是使用@WebMvcTest
测试控制器
如果您的测试是事务性的,那么在测试之后不会提交和回滚任何内容。但是,它仅在事务内部可见。当您调用一个实际端点时,该端点没有看到数据,只是因为它尚未提交。使用@Transactional
进行完整的集成测试是行不通的(在使用<代码> MoCKMVC < /COD>时,它会起作用,因为它不会发出实际请求并在同一线程和事务中运行。这是有意义的。那么,在每次集成测试之后/在每次集成测试之前重新设置数据库状态通常是什么?只是在<代码> >中删除所有的< < /代码>方法)。您是否考虑转换COM?你能把答案写下来,这样我就可以接受它,并把它提供给别人吗?