Продолжаем разработку нашего многомодульного приложения…

Введение

В этой истории мы собираемся углубиться в создание этого проекта, показав, как заполнить ответы HTTP-запросов, как пройти большинство тестов, которые мы в настоящее время реализовали, и начнем смотреть, как реализовать обмен сообщения с использованием RabbitMQ.

Контекст

Начиная с того места, где мы остановились в предыдущей истории (если вы хотите посмотреть здесь), мы продолжим разработку этого решения, многомодульного калькулятора, который использует RabbitMQ для связи между компонентами и HTTP-запросы для взаимодействия с пользователи. Обязательно ознакомьтесь с предыдущей историей, чтобы иметь полное представление о проекте, но в случае, если вы этого не сделаете, общая цель показана на рисунке ниже:

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

Индекс

  • Наличие поля результата с результатом вычисления
  • Можем ли мы извлечь больше пользы из текущего теста?
  • Обмен сообщениями с помощью RabbitMQ
  • Получить реальность

Наличие поля результата с результатом расчета

Продолжая с того места, где мы остановились в предыдущей истории, мы поймем, как вернуть поле результата в HTTP-ответе, чтобы наш ранее созданный тест мог правильно подтвердить заполняемое новое поле результат. Для заполнения этого нового поля мы можем думать о нашем теле JSON как о карте ключей и их значений и передавать карту объекту ResponseEntity. Теперь наша обновленная конечная точка должна выглядеть так:

С нашим текущим приемочным тестом, реализованным ранее, теперь мы должны увидеть его прохождение с этим дополнением.

Можем ли мы извлечь больше пользы из нашего текущего теста?

Итак, давайте подведем итоги: мы создали наш первый приемочный/интеграционный тест. Это проходит, что мы могли бы сделать сейчас?

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

Объект сообщения операции

Как уже упоминалось ранее, нам нужно будет перенаправить эти запросы другому компоненту. Поскольку от этих двух компонентов может отправляться и возвращаться множество сообщений, у нас уже есть 4 фрагменты информации, склеенные вместе:

  • 2 операнда
  • 1 оператор
  • результат расчета

В этом случае нам имеет смысл создать объект, который мы назвали OperationMessage:

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

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

Давайте сделаем шаг назад и поймем, что делает этот кусок кода:

  • строка 6.Мы тестируем CalculatorController, это наш тестируемый класс, поэтому мы используем аннотацию InjectMocks, что означает, что все зависимости этого класса будут макетами. Это то же самое, что сказать, что для всех зависимостей, которые использует этот класс, их поведение будет смоделировано (иначе «издеваться»), тем самым проверяя нашу логику.
  • строка 9-Поскольку при отправке расчета мы будем использовать протокол обмена сообщениями, это больше не является обязанностью контроллера (который должен обрабатывать только HTTP-запросы). Таким образом, RequestProcessor требуется для выполнения логики внедрения сообщения в очередь и всех этих обязанностей, связанных с обменом сообщениями. При этом используется аннотация Mock, поскольку нам нужно будет знать только, что мы вызываем один из методов RequestProcessor, а не подтверждаем поведение, которое он выполняет внутри.
  • строка 12.Метод setup() используется для подготовки набора тестов, в данном случае мы используем аннотацию BeforeEach, гарантируя, что каждый раз при выполнении теста метод setup вызывается перед любым тестом. работает.
  • строка 21-Наконец мы добрались до нашего теста. Мы просто просим наш CalculatorController выполнить сумму двух BigDecimal, а затем проверяем, что метод отправки запускается из requestProcessor. На данный момент этого достаточно, чтобы гарантировать, что метод отправки вызывается всякий раз, когда вызывается конечная точка суммы.

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

Мы продвинулись вперед? Да! Мы надеемся, что, как только наш первоначальный приемочный тест будет пройден, мы не будем выполнять вычисления в модуле RestController, а будем выполнять их, связываясь с другим модулем, который вернет нам результат.

Обмен сообщениями с RabbitMQ

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

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

  • Очереди работы
  • Опубликовать/подписаться
  • Маршрутизация
  • Темы
  • RPC
  • Издатель подтверждает

Мы собираемся двигаться вперед в этом случае с RPC, мы хотим не терять ответы на наши сообщения и самое главное мы хотим получить результат выполненного нами расчета, а не путать его с другими ответами от других Сообщения. Если вы хотите взглянуть на другие параметры конфигурации, я рекомендую вам начать с раздела Начало работы RabbitMQ здесь.

На данном этапе мы должны смотреть на следующую структуру компонентов:

Просто краткий обзор диаграммы компонентов, мы расширяем (увеличиваем) концепцию «остального интерфейса» и понимаем, что у нас есть 2 основных компонента, сначала контроллер, а затем процессор запросов (звучит не совсем идеально, но будет сделать пока). Идея использования такого абстрактного имени («Обработчик запросов») заключается в том, что в будущем нас может заинтересовать обработка сообщений с использованием другого протокола связи, это означает, что на самом деле этот обработчик запросов является не чем иным, как простым интерфейсом, который каждый сеанс связи протокол, который мы реализуем, необходимо соблюдать, гарантируя, что мы можем легко поменять способ, которым мы хотим общаться с Калькулятором. В следующем разделе мы подробно обсудим обработчик запросов.

Получение реального

Теперь, когда у нас есть идеи в простой диаграмме, мы можем перейти к самому коду. Теперь мы рассмотрим нашу недостающую часть, обработчик запросов:

Как упоминалось ранее, это настолько просто, насколько это возможно, идея здесь состоит в том, чтобы гарантировать, что мы создадим базовый объект OperationMessage, способный хранить выполняемую операцию и значения. Мы отправляем это сообщение калькулятору, чтобы этот компонент заполнил поле «результат». Затем мы просто возвращаем тот же объект с заполненным полем результата и заполняем тело HTTP-запроса результатом запрошенной операции. Мы вернемся к реализации этого интерфейса позже, но сначала нам нужно понять, как настроить экземпляр RabbitMQ для приема наших сообщений, это то, что будет рассмотрено в следующей истории.

Заключение

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

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

Рекомендации

https://www.rabbitmq.com/getstarted.html