Nano Hash - криптовалюты, майнинг, программирование

Тест интеграции Spring Boot не проходит, если @Transactional

У меня есть простое приложение Spring Boot, использующее репозитории Spring Data JDBC и предоставляющее REST API. Кажется, все работает нормально, за исключением моих интеграционных тестов. См. Ниже выдержку из конфигурации репозитория.

@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 с полноценным интеграционным тестом не сработает (оно будет работать при использовании MockMvc, потому что это не создает фактический запрос и выполняется в том же потоке и транзакции. 09.12.2020
  • В этом есть смысл. Какова же тогда обычная практика для сброса состояния базы данных после / перед каждым интеграционным тестом? Просто удалить все @AfterEach методом? Не могли бы вы преобразовать свой комментарий в ответ, чтобы я мог принять его и сделать доступным для других? 09.12.2020

Ответы:


1

Использование @Transactional с системным тестом не сработает.

Что происходит, когда данные вашего @BeforeEach метода вставляются в базу данных, но транзакция никогда не фиксируется. Данные видны только внутри одной транзакции.

Теперь вы отправляете HTTP-запрос на сервер, который открывает новое соединение с базой данных и запускает новую транзакцию. Однако, поскольку данные из другой транзакции не зафиксированы, она ничего не увидит.

@Transactionl будет работать только при использовании MockMvc, поскольку он будет выполняться внутри той же транзакции и потока. Когда выполняется фактический HTTP-запрос, это не так.

Использовать настройку данных для каждого теста, хотя при выполнении полного теста системы следует проявлять осторожность! вы либо:

  1. Напишите свой тест так, чтобы это не имело значения, действительно ли вам нужен системный тест.
  2. используйте MockMvc для запуска вашего теста вместо фактического HTTP-запроса, который заставит его (повторно) использовать ту же транзакцию.
  3. Не пишите системный тест, а используйте @WebMvcTest для тестирования вашего контроллера
09.12.2020
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..