Skip to content

Latest commit

 

History

History
296 lines (203 loc) · 13.6 KB

README_RU.md

File metadata and controls

296 lines (203 loc) · 13.6 KB

Actions codecov Go Report Card

Mocker — веб-сервер, который эмулирует поведение настоящего бэкенда.

Фичи

  • URL-Query prams matching — выбирает мок в зависимости от query параметров в запросе и в моке.
  • JSON-Body prams matching — выбирает мок в зависимости от JSON-тела в запросе и в моке.
  • Caching Proxy — может проксировать запросы клиента на реальный бэк, записывать результат в мок и возвращать его клиенту.
  • Отключение определенного мока или всех моков, кроме одного.
  • Задержка ответа для конкретного мока.
  • Итеративные ответы: несколько моков с определенным URL будут возвращаться по очереди — если нет матчинга по параметрам.
  • Файл сервер: можно раздавать статический контент

Мы не планируем поддерживать реляцию моков. Моки — это просто файлы: они никак не связаны между собой и никак не изменяются самим Mocker-ом.

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

Если реляция вам все-таки нужна, используйте матчинг query или body параметров.

Принцип работы

Принцип работы прост:

  • Пользователи пишут моки. Мок описывает что Mocker должен вернуть в ответ на запрос.
  • Mocker читает данные вов ремя старта либо после запрос GET /update_models (ниже будет описано как делать это автоматически)
  • Когда Mocker получает запрос он находит подходящий мок и возвращет его клиенту.

Принцип работы простой, но под капотом все немного сложнее (:

Моки

Моковые файлы представляют из себя Json формата:

 {
    "isDisabled": bool,
    "isOnly": bool,
    "isExcludedFromIteration": bool,
    "url": string,
    "method": string,
    "statusCode": int,
    "responseDelay": int,
    "response": object,
    "request": object
    "responseHeaders": object
    "requestHeaders": {
        "key": "value",
         .....
     }
 }

Буквально здесь записано следующее:

На запрос с URL = url и Method = method вернуть ответ response с кодом statusCode

url

Может быть следующих видов:

/path/to/endpoint

Обычный URL. Во время получения запроса сервис будет сравнивать строки посимвольно.

/path/to/endpoint/{number}

URL с path-паттерном. Мок с таким URL будет реагировать на любой запрос, который удовлетворяет этому шаблону.

Например:

/path/to/endpoint/1 --> OK
/path/to/endpoint/item --> OK
/path/to/endpoint/1/2 --> FALSE

/path/to/endpoint/data?param={value}

URL c query-паттерном. Мок с таким URL сработает на запрос, содержащий заданные параметры. При этом если одного из параметров не будет в запросе, он не сматчится с шаблоном.

ВНИМАНИЕ

URL должен начинатья с /

method

Пишите названия HTTP методов в UpperCase.

НЕ get А GET

statusCode

Любое целое число. Желательно из известных HTTP-кодов

response

Это поле содержит Json, который вернется в ответ на запрос.

request

Поле содержит данные для поиска конкретного мока. Для него работает параметризация.

Допустим, мы хотим замокать процесс оформления заказа:

{
  "url": "/billing/create",
  "method": "POST",
  "request": {
    "shopId": "123",
    "paymentType": "card",
    "items": []
  },
  "statusCode": 200,
  "response": {
    "orderId": 123
  }
}

Тогда на запрос оформления заказа из магазина 123 при оплате по карте всегда будет отдан мок выше.

Но есть загвоздка. Такой мок будет сматчен с запросом только в том случае, если в запросе массив items пуст. То есть для каждой корзины (с разными товарами) придется задавать новый мок.

Чтобы это обойти, обновим мок:

{
  "url": "/billing/create",
  "method": "POST",
  "request": {
    "shopId": "123",
    "paymentType": "card",
    "items": "{items}"
  },
  "statusCode": 200,
  "response": {
    "orderId": 123
  }
}

Теперь мок будет возвращаться вне зависимости от значения items.

А теперь мы хотим, чтобы на запрос, способ оплаты которого не равен card, возвращалась ошибка.

{
  "url": "/billing/create",
  "method": "POST",
  "request": {
    "shopId": "123",
    "paymentType": "{ paymentType != card }",
    "items": "{items}"
  },
  "statusCode": 400,
  "response": {
    "msg": "Current paymentType is unsupported"
  }
}

Шаблоны

  • {value} — шаблон, описывающий любое значение.
  • {value != | > | < | >= | <= $const$ } — шаблон с выражением. Через | перечислены поддерживаемые операторы.

Операторы работают для ограниченного набора типов:

  • != для String, Int, Dobule
  • >, <, >=, <= для Int, Dobule

Особенности шаблонов с выражениями:

  • Если вы указали несуществующую операцию, мок сматчится.
  • Если тип данных в request не может быть использован в этом операторе, мок не сматчится.
  • Если значение $const$ не может быть приведено к типу данных в request, мок не сматчится.

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

requestHeaders

Если запрос содержит те же хедеры, что указаны в этом поле, мок будет сматчен.

Мок будет считаться сматченным, только если выполнены все условия матчинга (query, request, headers).

responseHeaders

Содержит список пар key-value, где key — имя хедера, а value — значение.

Например, если мы хотим чтоб мокер вернул заголовок X-Example-Header со значением example_value, пишем:

"responseHeaders": {
  "X-Example-Header": "example_value"
}

isDisabled

Флаг, который может перевести мок в состояние «выключен». Если значение isDisabled == true, мок не будет участвовать в выдаче.

Если значение false или nil, поведение стандартное.

isOnly

Флаг, который отключает все моки, кроме одного конкретного. Если для какого-то мока IsOnly == true, то в выдаче будет участвовать только этот мок. Все остальные будут считаться «выключенными».

Если для мока одновременно IsOnly == true и IsDisabled == true, то значение IsDisabled игнорируется.

Если IsOnly == true одновременно для нескольких моков, всегда будет отдаваться первый по порядку мок. Никакого итерирования (пока, во всяком случае) нет.

При этом счетчик итератора не сбрасывается. Если итератор указывал на n-й файл, то после включения и отключения IsOnly итератор все так же будет указывать на n-й мок.

responseDelay

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

То есть все моки, у которых значение этого поля != 0, будут замедляться на указанное время. Время измеряется в секундах.

По умолчанию: 0

isExcludedFromIteration

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

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

По-умолчанию: false

Конфигурация

Mocker конфигурирется через переменные окружения:

  • MOCKER_MOCKS_ROOT_DIR: string — путь к папке, в которой лежат моки.
  • MOCKER_SERVER_PORT: integer — порт, на котором Mocker должен слушать подключения.
  • MOCKER_LOG_PATH — путь до файла, в который Mocker должен писать логи. Логи пишутся в формате JSON.

Как установить и начать использовать

В корне репозитория содержатся следующие файлы:

  • docker-compose.yaml содержит всю необходимую конфигурацию и готов к запуску - docker-compose up -d.
  • Dockerfile содержит конфигурацию для запуска Mocker-а.
  • FSWatherDockerfile — контейнер, который слушает изменения в файловой системе (в папке, в которой лежат моки) и при изменениях автоматически делает запрос GET /updateModels.

Во время запуска композа могут возникнуть ошибки вида you try to mount directory to file (or vice versa). Если вы поймали такую ошибку, создайте вручную нужные файлы.

.filebrowser_config.json:

{
  "port": 80,
  "baseURL": "",
  "address": "",
  "log": "stdout",
  "database": "/eddb/database.db",
  "root": "/srv"
}

Во время работы просто добавьте в .git/exclude эти файлы.

File Server

По-умолчанию префикс для файлового сервера - /mfs, что означает Mocker File Server.

Как это работает:

Mocker получает запрос - https://mocker.youthost.com/mfs/projectName/featureName/picture.png Mocker проверяет, если URL Path содержит mfs как первая часть пути, то оставшуюся часть пути использует как путь к файлам.

То есть, пусть у нас есть такая структура:

  • mocks_root_dir -- projectA -- checkout -- mock1.json -- img.png -- file.pdf

То, URL Path для файлов будет выглядеть так:

  • img.png -> /mfs/projectA/checkout/img.png
  • file.pdf -> /mfs/projectA/checkout/file.pdf

Так можно раздавать любой контент, в общем-то.

Roadmap

  • Добавить поддержку form-url для request матчинга

Contributing

Буду рад багрепортам, фичареквестам и вашим PR-ам!