Повышение тестируемости с внедрением зависимостей в JavaScript: практические примеры
Вы, вероятно, читали, что внедрение зависимостей (или DI) — это отличный инструмент, который помогает писать лучший код. Если вы, как и я, слышали или читали об этом так… много… раз, но никогда не видели и не понимали, как это на самом деле работает, вас ждет угощение. Сегодня мы рассмотрим несколько практических примеров того, как DI действительно помогает.
С возвращением, энтузиасты кодирования! Сегодня мы обратим внимание на важнейший аспект использования DI: тестируемость.
Тестируемость — это простота тестирования нашего кода.
Чтобы проиллюстрировать это, мы вернемся к кофейне Джейн. Итак, хватайте свою любимую чашку чая ☕️ и давайте погрузимся в мир тестируемости и внедрения зависимостей!
Тестирование…
«Тестирование, тестирование, тестирование» — мы так часто слышим это. Что это вообще значит?
Как программисты, мы все время тестируем — запускаем команду на терминале, тестируем API с помощью такого инструмента, как Postman и т. д. Единственная разница в том, что большинство из нас тестирует код вручную. Когда я говорю тестирование, я имею в виду автоматизированное тестирование.
Написав автоматические тесты, мы можем проверить правильность нашего кода, выявить ошибки на ранней стадии и гарантировать, что будущие модификации не нарушат существующую функциональность, что повторяется.
Тестируемость, с другой стороны, заключается в написании кода, который легко тестировать. Внедрение зависимостей играет ключевую роль в достижении этого.
Быстрая установка
Лично мне нравится использовать Jest и Sinon для написания тестов. Jest — это среда тестирования, которую легко настроить и с которой легко работать, как и Sinon.
Если вы не знакомы с этими инструментами, не волнуйтесь. Вы должны быть в состоянии следовать в любом направлении.
Давайте добавим эти инструменты в наш проект.
yarn add -D jest sinon @types/jest
Бесстыдная вилка: если вы хотите узнать, как работает Синон, посмотрите мое видео на YouTube или эту статью
Как только это будет сделано, мы обновим файл package.json
, чтобы мы могли легко запускать наши тесты из CLI с помощью npm run test
, например так
{ "name": "coffee-shop", "version": "1.0.0", "main": "index.js", "license": "MIT", "scripts": { "test": "jest" }, "devDependencies": { "@types/jest": "^29.5.2", "jest": "^29.5.0" } }
Наконец, мы добавим каталог test
. Jest по умолчанию ищет тестовые файлы в этом каталоге и любые файлы, оканчивающиеся на .spec.js
или .test.js
.
Ваш первый тест
Мы напишем тесты для класса бариста Джейн.
Если вы читали приквел к этому посту, то помните, что мы отделили Barista
класс от CoffeeGuru
класса с помощью DI. Это позволило нам теперь создать поддельную реализацию его зависимостей и протестировать ее изолированно, т. е. сосредоточиться только на классе Barista
и не беспокоиться ни о чем другом.
При тестировании мы следуем структуре под названием Arrange
Act
Assert
. Это просто означает, что для каждого теста мы
- Организуйте — мир, создавая экземпляры, настраивая начальные данные и т. д.…
- Act — вызвать функцию или класс, которые мы тестируем. Это также называется тестируемой системой (или SUT).
- Утвердите — или убедитесь, что результат вызова SUT — это то, что вы ожидаете.
Выполнение вышеуказанного с npm run test
приводит к следующему
Хорошо хорошо. Все это прекрасно, но где же эта «сила DI», о которой вы говорите? Мне нравится твой энтузиазм! Давайте копать.
Сгибание кода
Одним из преимуществ внедрения зависимостей является возможность запускать наш код в различных сценариях. Давайте рассмотрим тестовый случай, когда кофейный гуру не может предоставить кофейные зерна, что вынуждает бариста изящно справиться с ситуацией.
Как видите, мы изменили CoffeeGuru
, чтобы вернуть неожиданное значение. В текущей реализации этот тест не проходит.
Это возможность обновить нашу реализацию, чтобы справиться с этой ситуацией. Давайте обновим наш класс Barista
, чтобы он обрабатывал этот случай.
Наконец, мы протестируем еще один сценарий, в котором мы моделируем ошибку в процессе извлечения молока. Еще раз, мы сначала обновляем наш тест, чтобы настроить ожидания от нашего кода и увидеть, что наш тест не проходит.
Теперь, когда мы знаем, что это может случиться, мы обновим наш код, чтобы обработать это, заключив его в блок try...catch
.
Там! Наши тесты снова стали зелеными.
Если вы не заметили, здесь есть закономерность. Каждый из приведенных выше примеров имел следующую форму:
- Напишите тестовый сценарий
- Запустите тест и убедитесь, что он не работает
- Обновите код для обработки сценария
- Повторно запустите тест и убедитесь, что он прошел.
Этот цикл известен как цикл Red-Green-Refactor и является мантрой разработки через тестирование.
Заключение
Разделяя зависимости и заменяя их макетами или заглушками (вместе называемыми подделками), мы можем изолировать и тщательно протестировать наш код. Возможность моделировать различные сценарии и изящно обрабатывать ошибки обеспечивает надежность и надежность наших приложений. Итак, используйте потенциал внедрения зависимостей и поднимите свою тестовую игру на новый уровень!
Я надеюсь, что теперь вы можете увидеть, как DI помогает в реальном мире, и хорошо понимаете, как его использовать в реальном мире.
Буду рад узнать, что вы думаете об этих статьях!
Полезны ли они? О чем вы хотите узнать больше? React, Node/Express/базы данных и ORM?
Я работаю инженером полного цикла около 9 лет и обладаю обширным опытом: от веб-разработки с помощью React и Vue до проектирования микросервисов и настройки и автоматизации инфраструктуры.
Как всегда, если вам понравилась эта статья и вы узнали что-то новое, покажите свою любовь с помощью 👏 . Это действительно помогает охватить более широкую аудиторию и мотивирует меня писать больше. 🙌🏻
До скорого…