我有一个使用@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]]].

最佳答案

@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

10-06 11:21