Почему очень важно тестировать ваше приложение в целом, а не пропускать часть БД.

Зачем тестировать также часть БД?

При разработке приложения на долгосрочную перспективу абсолютно необходимо покрыть как можно больше — и разумно — тестами, чтобы убедиться, что любые модификации кода не изменят желаемое поведение или не приведут к критическим ошибкам.

В большинстве серверных приложений база данных является одной из наиболее важных частей, поэтому пропуск или насмешка над всей ее логикой — это просто бомба, ожидающая своего срабатывания. Просто представьте, что ваши серверы получают сотни запросов в секунду, и внезапно ВСЕ из них выходят из строя или вызывают побочные эффекты, потому что вы не протестировали должным образом код, взаимодействующий с базой данных… 💣💥🤯

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

Почему In-Memory DB? Разве мы не можем просто использовать «нормальный»?

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

Если бы мы подошли к этому очень прямолинейно, мы бы загрузили MongoDB как двоичный файл и установили его или запустили образ MongoDB Docker, чтобы иметь запущенный локальный экземпляр нашей MongoDB, с которым мы могли бы взаимодействовать. И хотя он определенно рекомендуется (в данном случае я бы предпочел Docker) для РУЧНОГО тестирования на вашем локальном компьютере, это не лучший способ для автоматического тестирования.

Есть несколько проблем с этим подходом:

  • Это определенно не сработает для конвейеров CI/CD, по крайней мере, без МНОГО дополнительных затрат времени и ресурсов, таких как запуск чистого контейнера докера для каждого тестового примера. Стоит много ресурсов и вводит много дополнительной сложности.
  • При локальном запуске тестов вам всегда придется полностью очищать локальную БД, чтобы создать чистое состояние для ваших тестов, что приведет к потере данных, которые вы могли бы в настоящее время использовать для ручного тестирования.
  • Не очень эффективно всегда писать в реальную существующую БД и полностью очищать ее после каждого теста. В памяти просто быстрее

Таким образом, должно быть совершенно ясно, что подход в памяти должен быть предпочтительным.

Фактический код

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

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



Abszissex/medium-in-memory-mongodb-node
Внесите свой вклад в разработку Abszissex/medium-in-memory-mongodb-node, создав учетную запись на GitHub.github.com



Настройка тестовой конфигурации

Для использования MongoDB в памяти в ваших тестах вам необходимо установить две зависимости dev, я предполагаю, что вы уже установили Jest и клиент MongoDB.

npm i --save-dev mongodb-memory-server @shelf/jest-mongodb

После этого нам нужно создать несколько файлов для настройки Jest, чтобы он использовал MongoDB в памяти и запускал ее перед запуском тестовых случаев.

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

Настройте фактические тесты

После настройки наших тестовых конфигураций мы должны определить наши тесты.

Если вы проверите вышеуказанный репозиторий, вы увидите, что у нас есть dbhelper.ts и соответствующий тестовый файлdbhelper.spec.ts. Мы не используем какой-либо причудливый HTTP-сервер в этом примере/проекте, поскольку он просто не нужен, даже если он может быть наиболее распространенным вариантом использования при использовании некоторой БД.

Фактическая реализация dbhelper.ts не важна, просто ожидайте, что она предоставляет класс с именем DBHelper с общедоступными методами для

  • Запуск — createConnection(mongoHost, mongoDbName)
  • Выключение — closeConnection()
  • Добавление людей — addPersonsToDb(persons)
  • Получение всех лиц — getPersonsFromDb()

Но, конечно, вы можете проверить фактическую реализацию в репозитории.

Поэтому, прежде чем мы начнем выполнять тесты, мы должны напомнить себе, что наш файл jest.setup.ts заботится о предоставлении переменных среды для установления соединения с MongoDB — обычно это делается с помощью обычных переменных среды при запуске приложения — и гарантирует, что MongoDB находится в чистом состоянии. перед каждым тестовым запуском. Также обратите внимание, что следующие тестовые примеры являются просто примерами и не охватывают все возможные тестовые примеры, которые вы должны написать в реальной реализации.

Если мы теперь используем npm run test для запуска выше dbhelper.spec.ts, мы увидим, что все тестовые случаи проходят за короткий промежуток времени.

Исправление проблем

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

Так что перепроверьте, правильно ли вы закрыли соединения в блоках jest.setup.ts и dbhelper.spec.ts в блоках afterAll и нет ли утечек.

Вывод

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

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

Спасибо, что нашли время прочитать мою статью.

Если у вас есть какие-либо вопросы или дополнения, не стесняйтесь использовать раздел комментариев или написать мне в LinkedIn или Twitter, чтобы связаться со мной 😊