Модульное тестирование с сервером БД, работающим в докере, является гораздо лучшим выбором, чем Sqlmock, обычно

Около двух лет назад я написал статью, обсуждающую, как тестировать приложение GORM с помощью Sqlmock.

Время летит незаметно, и я понимаю, что большинство разработчиков не принимают такой подход (по крайней мере, в моей команде). Написание тестового примера с использованием Sqlmock слишком сложно для начала.

Основная проблема заключается в том, что вам нужно написать весь фрагмент SQL вручную, а затем сравнить его с выводом GORM. Эта рабочая нагрузка уже намного больше, чем написание кодов для тестирования. В конце концов, причина, по которой мы используем GORM, заключается в том, чтобы не писать необработанный SQL вручную.

Нам нужно найти лучший способ.

Улучшить процесс модульного тестирования

В общем, тестировать приложение БД сложно. Основная причина — сам сервер базы данных.

  • Если команда разработчиков использует удаленный сервер базы данных, конфликт данных неизбежен.
  • Если мы создадим учетные записи для каждого разработчика на этом сервере базы данных, то модульные тесты должны запускаться с разными учетными записями. И кто-то должен вести эти учетные записи.
  • Если мы потребуем, чтобы каждый разработчик установил и настроил сервер базы данных на своей локальной рабочей станции, мы усложним настройку среды разработки.

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

Процесс изображения ниже:

  1. Запустите сервер базы данных с докером перед каждым набором тестов. открыть соединение GORM с этим сервером
  2. Перед запуском каждого тестового случая очищайте данные в базе данных и при необходимости заново создавайте таблицы.
  3. Запустите все тестовые случаи
  4. Остановить сервер базы данных после выполнения набора тестов

Теоретически мы могли бы управлять демоном docker с помощью командной строки. Но с помощью dockertest эта цель может быть легко достигнута.

Модульное тестирование сервера базы данных в Docker

Вот пошаговое руководство по модульному тестированию приложения GORM с реальным сервером базы данных, работающим в докере.

мы повторно используем пример приложения из предыдущей статьи. Вы можете найти исходный код на Github.

В качестве примера в этой статье мы используем Postgres, но он может работать и с любой другой базой данных.

Настройка набора тестов

Согласно схеме последовательности делаем ряд заготовок:

  • В BeforeSuite мы создаем экземпляр *gorm.DB и функцию для очистки ресурсов докера. Функция setupGormWithDocker будет объяснена позже.
  • В AfterSuite мы вызываем cleanupDocker для освобождения ресурсов, связанных с докером.
  • В BeforeEach мы удаляем схему по умолчанию, а затем создаем ее заново, чтобы убедиться, что база данных чиста и готова перед каждым запуском тестового примера.

Ниже приведены пояснения к основной функции setupGormWithDocker:

  • Создайте пул ресурсов докеров с dockertest.NewPool, который используется для запуска контейнера докеров.
  • Укажите имя образа, версию образа и переменную среды с помощью dockertest.RunOptions.
  • fnConfig — это функция для управления политикой начальной загрузки. В этом случае нам нужно, чтобы docker-контейнер автоматически удалялся после остановки и никогда не перезапускался автоматически.
  • Мы используем pool.RunWithOptions для запуска контейнера, затем создаем функцию очистки fnCleanup.
  • Так как запуск контейнера займет некоторое время, нам нужно дождаться готовности контейнера. Только после этого мы можем вернуть экземпляр *gorm.DB. Здесь на помощь приходит pool.Retry. pool.Retry будет многократно выполнять функцию параметра, пока функция не вернет nil (что означает, что контейнер готов)

Создание тестового примера

С подготовкой в ​​наборе тестов мы могли бы получить пригодный для использования экземпляр *gorm.DB, подключающийся к локальному серверу базы данных, и база данных будет очищаться перед каждым выполнением тестового примера.

  • В BeforeEach мы создаем экземпляр Repository для тестирования. Вызов repo.Migrate для автоматического создания таблиц, а затем создания образца данных блога.
  • Тестовые случаи довольно интуитивны. Мы вызываем методы репо и проверяем, что ожидаемый результат возвращается. Здесь нет никакой имитации, так как мы используем настоящий сервер базы данных.
  • По сравнению с Sqlmock, нет необходимости писать необработанный SQL вручную, и мы можем завершить весь тестовый пример менее чем за сотню строк кода.

Другие важные примечания

  • dockertest будет извлекать образы, если это необходимо, но без подсказки о ходе загрузки. Мы предлагаем запустить docker pull postgres:14 перед первым запуском тестового примера.
  • Запуск набора тестов может занять несколько секунд, так как нам нужно запустить сервер базы данных Postgres. Это может показаться медленнее, чем большинство модульных тестов в памяти, но это приемлемо.
  • Во время pool.Retry будут выводиться некоторые ошибки соединения. Если вам не нравятся помехи, передайте &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)} в gorm.Open, чтобы закрыть журнал
  • Ваше приложение может зависеть от некоторого расширения Postgres. В этом случае вы можете заменить стандартный образ Postgres на пользовательский. Например, если вам нужно постгрес все, вы можете использовать этот образ докера.

Заключение

  • Тестирование приложения GORM на реальном сервере базы данных имеет огромное преимущество.
  • С помощью dockertest локальный докер-контейнер может беспрепятственно работать с модульным тестированием Golang.
  • В отличие от Sqlmock, вся логика БД работает на реальном сервере БД, никаких моков не нужно, а тестовые случаи значительно упрощены.
  • Есть ли какая-то причина придерживаться Sqlmock сейчас?
  • Для получения полного исходного кода посетите его репозиторий.

Ваше здоровье!

Ресурсы

Как выполнить модульное тестирование приложения GORM с помощью Sqlmock.

Want to Connect?
Follow me on Twitter.