Транзакционный тест Spring Boot с MySQL 8 откатывает транзакцию, но строка все равно вставляется - PullRequest
1 голос
/ 03 октября 2019

Обычно, когда я запускаю приложение Spring Boot с Spring Data JPA, в тестах происходит откат транзакций автоматически, и тестовая база данных не изменяется. Это поведение не работает, однако, с MySQL8.

У меня есть тривиальный POJO под названием Category.

@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, хотя откат происходит, вставленный элемент остается.

Что здесь отличается? Как это исправить, чтобы вставка сбрасывалась в конце теста?

Ответы [ 2 ]

1 голос
/ 04 октября 2019

Сделайте ваши тестовые методы общедоступными, потому что из документации :

Из-за основанной на прокси природе среды Spring AOP, вызовы внутри целевого объекта по определениюне перехваченДля прокси-серверов JDK могут быть перехвачены только вызовы методов открытого интерфейса на прокси.

Если метод не является общедоступным, ошибка не выдается.

Я полагаю, вы используете значение по умолчанию(Прокси JDK, а не CGLIB)

0 голосов
/ 03 октября 2019

Поскольку транзакция должна быть зафиксирована явно. Поэтому я думаю, что вам нужно установить свойство autocommit в false. как это

<property name="hibernate.connection.autocommit">false</property>
...