Приветствую тебя, уважаемый читатель Хабра! Меня зовут Артур Вартанян и я работаю в компании “Рексофт” Java-разработчиком. Тема с testcontainer-ами относительно не новая, первые статьи на англоязычных ресурсах встречаются с 2016 года, но не смотря на это, до сих пор на просторах веба крайне мало гайдов для их развертывания из коробки. В большинстве своем это туториалы, где собрана солянка из зависимостей и аннотаций, которые мало того, что не нужны, но еще и могут запутать разработчика, решившего  с ними познакомиться. В этой статье я опишу свой практический кейс по развертыванию тестовых контейнеров для базы данных PostgreSQL. Основная задача их использования - быстрый deploy нужного сервиса в контейнере за небольшое время. В дополнении для наглядности запустим туда FlyWay миграции. Мы не будем говорить о плюсах и минусах контейнеризации и интеграционных тестов, а сразу приступим к делу. Нам потребуется: Docker. Он нужен для того, чтобы запускать контейнер и управлять им. Spring MVC API (REST) с некоторым количеством тестов. Приложение, которое будет запускать тесты в контейнере, должно иметь хотя бы один интеграционный тест, иначе смысла в использовании контейнера нет. Класс контроллера: Класс тестов: Для того, чтобы переписать код под использование testcontainers, необходимо добавить всего лишь 3 зависимости (для примера используется Gradle / версии актуальны на момент написания статьи): spring-boot-starter-test - для поднятия контекста тестов; testcontainers:postgresql - PostgreSQL для контейнера; testcontainers:junit-jupiter - JUnit Jupiter для контейнера. Если проект не специфичный и не должен поддерживать связку legacy тестов вперемешку с новыми, то других зависимостей не требуется! Иначе из-за одной неверно подтянутой аннотации testcontainer-ы могут просто не подняться, и понять в чем дело будет тяжело, так как логи об ошибке не будут явно указывать на проблему зависимостей. Все свои другие библиотеки от JUnit, которые вы использовали до добавления testcontainer-ов нужно удалить - они ни к чему.   Теперь, после добавления нужных библиотек, необходимо создать класс, который будет отвечать за конфигурирование и настройку контейнера: @SpringBootTest - поднимает ApplicationContext для запуска тестов и имитирует среду для тестирования близкую к полноценному запуску приложения. @Testcontainers - аннотация для JUpiter интеграционных тестов. Находит все поля, помеченные аннотацией @Container, и вызывает их методы контроля за жизненным циклом для контейнера. @AutoConfigureMockMvc - в тестах я часто использую MockMVC класс, поэтому для его настройки из  коробки я использую данную аннотацию. @ContextConfiguration - аннотация определяет метаданные уровня класса, которые используются для определения того, как загружать и настраивать ApplicationContext для интеграционных тестов. На самом деле, тут можно обойтись и без данной аннотации, так как мы уже используем @SpringBootTest, но с ним код будет чище и появится возможность сразу создавать переменные окружения для конфигураций ApplicationContext-а.  @TestPropertySource - указываем путь нахождения файла application.properties для тестов. Статичное поле postgreSQLContainer, помеченное аннотацией @Container, по сути является флажком для аннотации @TestContainer, который понимает, что необходимо запустить тестовый контейнер PostgreSQL и управлять его жизненным циклом. Тут же вызываются методы withReuse() и withDatabaseName(). withResure() с флажком true - держит контейнер в активном состоянии до тех пор, пока не исполнятся все тестовые методы, а также дает возможность переиспользовать контейнер для каждого теста без его затухания и поднятия нового экземпляра. withDatabaseName() - получает на вход название базы данных (можно указать рандомный и также вынести в переменную окружения - см.ниже). Вложенный статичный класс Initializer реализует ApplicationContextInitializer и при инициализации создает переменные окружения. В TestPropertyValues  мы их и создаем по принципу ключ-значение. По сути после поднятия контекста у нас будут доступны три переменные, которые мы можем использовать там, где это необходимо, например, при накатке FlyWay миграций. Класс самих тестов также немного преобразуется и станет наследником SpringBootApplicationTest, одновременно меняя свои аннотации на JUnit Jupiter: Напоследок application-properties.yml файл (создаем в тестах новый файл в папке ресурсов): Так как приложение во время работы должно использовать базы данных от тестконтейнера, необходимо прописать для него строку подключения. Как уже отмечалось выше, в переменные окружения при поднятии тестового контекста уже все было вынесено, а именно: CONTAINER.URL - строка подключения к БД; CONTAINER.USERNAME - имя пользователя; CONTAINER.PASSWORD - пароль пользователя. Подставив их в application-properties.yml файл, можно получить полностью настроенный контекст приложения. P.S. При указании в application-properties значений с окружения, используется запись вида: ${НАЗВАНИЕ_ПЕРЕМЕННОЙ}. Дополнение: Для большей наглядности на базу PostgreSQL от тестконтейнера накатим FlyWay миграции, чтобы получить базу идентичную с приложением. Для этого в тестовый application-properties.yml файл нужно добавить всего лишь пару строк кода, где также будут указаны данные для подключения и запуска миграций: При запуске тестовых классов или методов, в Docker (Docker Desktop в моем случае) можно будет увидеть поднятый контейнер, который сразу же после завершения тестов потухнет. Надеюсь данная статья была для Вас полезна и в дальнейшем будет помогать тратить меньше времени на запуск и настройку тестовых контейнеров, ведь один из главных смыслов их использования - это быстрый deploy нужного сервиса в контейнере за небольшое время.  Разработчик