【问题标题】:SpringBootTest not rolling back transaction in spring boot 2SpringBootTest 没有在 Spring Boot 2 中回滚事务
【发布时间】:2018-05-03 03:28:16
【问题描述】:

我有一个使用@DataJpaTest@Transactional 的非常简单的弹簧测试:

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
@Transactional
@Rollback
@ComponentScan(basePackages = "com.acma")
public class FooTest {
  @Autowired
  private EntityManager em;

  @Test
  public void persist() throws Exception {
    em.persist(new Foo());
  }
}

@Entity
public class Foo {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
}

根据文档,每个测试用例都应该在自己的事务中运行,并在每个测试用例结束时回滚,但这并没有发生。

更奇怪的是,在我看到的日志中:

2018-05-02 19:47:07.246  INFO 97919 --- [           main] o.s.t.c.transaction.TransactionContext   : Began transaction (1) for test context [DefaultTestContext@317890ea testClass = FooTest, testInstance = com.acma.FooTest@2c719bd4, testMethod = persist@FooTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@53aa38be testClass = FooTest, locations = '{}', classes = '{class com.acma.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@37a0ec3c key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5be6e01c, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@7ce3cb8e, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@70e8f8e, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@e831c7a, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@636be97c], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@6f9e08d4]; rollback [true]
Hibernate: insert into foo values ( )
2018-05-02 19:47:07.575  INFO 97919 --- [           main] o.s.t.c.transaction.TransactionContext   : Rolled back transaction for test context [DefaultTestContext@317890ea testClass = FooTest, testInstance = com.acma.FooTest@2c719bd4, testMethod = persist@FooTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@53aa38be testClass = FooTest, locations = '{}', classes = '{class com.acma.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@37a0ec3c key = [org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5be6e01c, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@7ce3cb8e, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@70e8f8e, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@e831c7a, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@636be97c], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]].

【问题讨论】:

  • 您如何/在什么时候尝试验证事务没有回滚?

标签: java spring spring-boot spring-test


【解决方案1】:

@DataJpaTest 默认情况下,数据 JPA 测试是事务性的,并在每次测试结束时回滚

所以你不需要额外的@Transactional 和@Rollback

这里有一个例子,看看 @AfterTransaction 及其输出。

在您的示例中,您可以尝试使用此方法检索您保存的实体,但您不会找到它。

 @RunWith(SpringRunner.class)
 @DataJpaTest
 public class TransactionTest {

   @Autowired PersonRepository repo;

   @Before
   public void showCountBefore() {
     System.err.println("before: " + repo.count());
   }

   @After
   public void showCountAfter() {
    System.err.println("after: " + repo.count());
   }

   @AfterTransaction
   public void showCountAfterTransaction() {
     System.err.println("after tx: " + repo.count());
   }

   @Test
   public void testRollback() {
     repo.save(new Person("Deyne", "Dirk", "dirkdeyne"));
     System.err.println("saved: " + repo.count());
   }

}

这会打印出来

  • 之前:5
  • 已保存:6
  • 之后:6
  • 发送后:5

【讨论】:

  • 我更改了我的示例,删除了您提到的注释,但没有帮助,这是修改后的版本:gist.github.com/csokol/a37356da3400d57edc1e460e9674efdc 也许这不起作用的原因是我没有使用内存D b?另外我正在使用spring boot 2.x ...
  • 是的,当我将其更改为使用内存数据库(删除@AutoConfigureTestDatabase(replace = Replace.NONE))时,事务回滚工作。
  • 这很奇怪! @AutoConfigureTestDatabase(replace = Replace.NONE) 在我的示例中没有任何区别。我确实尝试过使用 EntityManager 持久化,它也可以工作......也许你必须在持久化之后刷新em.flush();
  • 你用的是哪个spring boot版本?
  • @DirkDeyne 我用这个stackoverflow.com/a/49997835/4188368得到了它的工作
猜你喜欢
  • 2018-11-05
  • 2020-04-28
  • 2020-03-11
  • 2018-09-03
  • 2018-06-17
  • 2020-06-29
  • 2018-03-25
  • 2016-10-07
  • 2017-11-07
相关资源
最近更新 更多