通常,当我使用Spring Data JPA做Spring Boot应用程序时,在测试中事务会自动回滚,测试数据库不会改变。然而,这种行为在MySQL8中不起作用。
我有一个名为Category的小POJO。
@Entity
@Table(name = "categories")
public class Category {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "category_id")
private Integer id;
@Column(name = "category_name")
private String name;
// ... constructors, getters and setters, etc, omitted ...
}下面是我的更简单的存储库接口:
public interface CategoryRepository extends JpaRepository<Category,Integer> {
}我有一个现有的数据库,下面是访问它的application.properties设置:
spring.datasource.url=jdbc:mysql://localhost:3306/dashboard
spring.datasource.username=admin
spring.datasource.password=not_password
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect表中目前有10个类别。我的测试检查它们,另一个测试插入一个新的。
@DataJpaTest
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
class CategoryRepositoryTest {
@Autowired
private CategoryRepository dao;
@Test
void findAll() {
List<Category> categories = dao.findAll();
assertEquals(10, categories.size());
}
@Test
void insertCategory() {
Category cat = new Category("Misc");
assertNull(cat.getId());
cat = dao.save(cat);
assertNotNull(cat.getId());
System.out.println(cat);
}
}请注意,@DataJpaTest已经包含了@Transactional。第二个测试的输出为:
2019-10-03 14:26:48.844 INFO 91485 --- [ Test worker] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@67e4b73d testClass = CategoryRepositoryTest, testInstance = com.kousenit.simpledemo.dao.CategoryRepositoryTest@3913544f, testMethod = insertCategory@CategoryRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@7314dd45 testClass = CategoryRepositoryTest, locations = '{}', classes = '{class com.kousenit.simpledemo.MyApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@3c6df497, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@351584c0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@8b9f8fd, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@15acb0c6, [ImportsContextCustomizer@76c5962 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@21f27cf2, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@67568498, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@4a3861f3]; rollback [true]
Hibernate:
insert
into
categories
(category_name)
values
(?)
Category{id=11, name='Misc'}
2019-10-03 14:26:48.880 INFO 91485 --- [ Test worker] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@67e4b73d testClass = CategoryRepositoryTest, testInstance = com.kousenit.simpledemo.dao.CategoryRepositoryTest@3913544f, testMethod = insertCategory@CategoryRepositoryTest, ...问题是,测试结束后,我的数据库中仍然有新的类别。在H2中,事务回滚了,但是在MySQL 8中,即使发生了回滚,插入的项仍然存在。
这里有什么不同?我如何修复它,以便在测试结束时重置插入?
发布于 2019-10-04 02:52:26
因为事务需要显式提交。因此,我认为您需要将自动提交的属性设置为false。像这样
<property name="hibernate.connection.autocommit">false</property>发布于 2019-10-04 16:18:39
将您的测试方法设置为公共的,因为从documentation
由于Spring框架基于代理的本质,根据定义,目标对象内的调用不会被拦截。对于JDK代理,只能拦截代理上的公共接口方法调用。
如果该方法不是公共的,则不会引发任何错误。
我想您使用的是缺省设置(JDK代理,而不是CGLIB)
发布于 2021-03-31 19:20:53
我不确定这是不是你的问题,但我得到了相同的行为,因为我在一个创建线程和它自己的事务的流中使用了"peek“,当所有测试一起运行时,它在数据库中留下了行。当它们一个接一个地运行时,这并没有发生。确保没有创建新的线程,也没有在代码内部进行控制
https://stackoverflow.com/questions/58225093
复制相似问题