Как организовать Unit-тесты при разных версиях БД на разных стендах?

«Как организовать Unit-тесты при разных версиях БД на разных стендах?» — вопрос из категории Тестирование, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Основной подход — изоляция тестов от реальных стендов.

1. Использование Testcontainers (рекомендуется для интеграционных тестов):

@Testcontainers
class UserRepositoryIntegrationTest {
    @Container
    static final PostgreSQLContainer<?> POSTGRES = 
        new PostgreSQLContainer<>("postgres:13-alpine")
            .withDatabaseName("testdb")
            .withUsername("test")
            .withPassword("test");

    @BeforeAll
    static void setup() {
        // Настройка DataSource на основе POSTGRES.getJdbcUrl()
    }
}

Преимущества: Тесты запускаются в изолированном Docker-контейнере с точной версией БД.

2. Использование встроенной/легковесной БД (например, H2):

# application-test.properties
spring.datasource.url=jdbc:h2:mem:testdb;MODE=PostgreSQL
spring.datasource.driver-class-name=org.h2.Driver

Важно: Проверять совместимость SQL-диалекта с целевой БД (PostgreSQL, MySQL).

3. Управление схемой через миграции (Flyway/Liquibase):

  • Миграционные скрипты гарантируют одинаковую схему на всех окружениях.
  • В тестах можно использовать spring.flyway.locations для специфичных тестовых миграций.

4. Мокирование слоя доступа к данным: Используйте Mockito, если тестируете бизнес-логику, а не работу с БД.

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    @Mock
    private UserRepository userRepository;

    @Test
    void shouldReturnUser() {
        when(userRepository.findById(1L)).thenReturn(Optional.of(new User()));
        // тест сервиса
    }
}

Правило: Тесты не должны зависеть от состояния внешних стендов. Версия БД в тестах должна быть либо фиксированной (Testcontainers), либо эмулированной (H2).