Разработать мок для проверки асинхронного обмена сообщениями с внешней системой. Как пример, рассмотрим некий кейс проверки валидности промокода внешней системой. По шагам: 1) Отправляем запрос в сервис внешней системы; Запрос PUT содержит поля (например, в headers): promotionalCode=correctPromotionalCode correlationId=рандомная строка, которую нужно будет вернуть в callback replyTo= адрес сервиса принимающего callback 2) Внешняя система отвечает синхронно - 204 No content; 3) Через 5 секунд внешняя система отправляет асинхронный callback (по адресу replyTo из запроса): Запрос POST  с телом сообщения: status = "success",      если promotionalCode запроса равен "correctPromotionalCode", в остальных случаях - "validationError"  correlationId = correlationId из запроса    Для решения данной задачи используем SoapUI. Данный инструмент достаточно гибок в плане создания "умных" моксервисов, тк позволяет написать скрипты, как на этапах запуска/остановки моксервиса (Start Script/ Stop Script), так и перед/после получения запроса (OnRequest Script/AfterRequest Script).  Начнем: 1) В SoapUI создать новый проект, например, "test-soapui-project" (либо выбрать существующий) и создать для него два REST MockService.    Первый назовем Validation REST MockService - имитирует сервис внешней системы: в Path произвольный путь к моксервису, например, "/SP/ValidationSystem", в Port значение порта на котором будет запущен мок, в Host значение "localhost".   Второй назовем Validation Receiving CALLBACK REST MockService - имитирует сервис принимающий callback (данный мок нужен для локальной проверки "Validation REST MockService" перед тем как мы его запустим на общем сервере): Аналогично в Path произвольный путь к моксервису, например, "/SP/SpHost"  2) В мок Validation REST MockService добавить: запрос PUT Указываем:  в Resource Path произвольный путь к методу внутри моксервиса, например, "/validation"  в Method указываем метод Rest запроса, в нашем случае PUT (шаг 1 в задаче) для запроса PUT добавить ответ 204 No content Указываем: в Http Status Code код ответа на запрос, в нашем случае "204 - No Content",  в Content | Media type тип ответа на запроса, в нашем случае "application/json". переменные в Properties: это переменные в которые будут сохранены поля promotionalCode, replyTo, correlationId из поступившего запроса PUT. OnRequest Script - данный скрипт будет выполняться перед отправкой синхронного ответа 204 No content (шаг 2 задачи). Получаем из запроса необходимые значения и записываем в  Properties: *log.info можно не использовать, носит информативный характер для проверки хода выполнения операций на вкладке  script log. AfterRequest Script - данный скрипт выполнится после отправки синхронного ответа. Тут наша задача сформировать callback на основании полученных данных, имитировать небольшую задержку (в нашем случае 5 секунд), отправить callback по адресу replyTo (шаг 3 задачи): Сам скрипт: 3) В мок Validation Receiving CALLBACK REST MockService  добавить: запрос POST Указываем:  в Resource Path произвольный путь к методу внутри моксервиса, например, "/callback"  в Method указываем метод Rest запроса, в нашем случае POST. для запроса POST добавить ответ 200 OK Указываем:  в Http Status Code код ответа на запрос, в нашем случае "200 - OK", в Content | Media type тип ответа на запроса, в нашем случае "application/json". OnRequest Script - в скрипте мы выводим сообщение, что callback успешно получен и смотрим, что в нем пришло: 4) Запустить оба моксервиса  5) Проверяем работу моксервисов  Отправляем запрос проверки валидации, например, через Postman: Выполняем PUT вызов метода validation на Мок 1 (Validation REST MockService), указывая в Headers 3 параметра, как описано в Задаче В replyTo указываем адрес сервиса принимающего callback - Мок 2 (Validation Receiving CALLBACK REST MockService) При выполнении запроса видим в ответе - 204 No Content. Проверяем в script log SoapUI , что callback пришел на Мок 2: Запуск моксервиса в Portainer: 1) В images добавляем образ для работы с моксервисами SoapUI: находим на docker hub  необходимый образ. в нашем случае fbascheper/soapui-mockservice-runner (https://hub.docker.com/r/fbascheper/soapui-mockservice-runner/)<o:p>   переходим в Portainer в  раздел images   по названию загружаем  необходимый образ  2) Разворачиваем стек для работы с моксервисами :  Составить Compose file: где: image - образ загруженный с docker hub (https://hub.docker.com/r/fbascheper/soapui-mockservice-runner/) volumes - указать где на сервере расположен проект soapUI и куда его необходимо расположить в контейнере, формат: "директория на сервере": "директория в контейнере" MOCK_SERVICE_NAME - название моксервиса внутри проекта soapUI PROJECT - путь к проекту soapUI в контейнере, формат: «значение "директория в контейнере" из volumes» + само название проекта(в нашем случае test-soapui-project) ports - указать внешний порт по которому моксервис будет доступен извне и на каком порте запущен в контейнере (значение port из soapUI), формат "внешний порт": "порт в контейнере" *в нашем примере проект soapUI разместили на сервере в /soapui/soapui-prj/ перейти в Portainer в раздел Stacks,  добавить новый стек: - указать в поле Name, как  будет назван наш стек, например, sp-soapui-mocks, - в Web editor копируем текст  Compose file, Deploy the  stack.  В результате будет сформирован стек sp-soapui-mocks, в котором запущен  сервис , указанный в compose file: Мы получили асинхронный моксервис , который удовлетворяет поставленной задаче. Сервис запущен на общем сервере и доступен всем участникам проекта. В данный момент он помогает нам разрабатывать и тестировать приложение при отсутствии API сторонней системы.