Я создал минимальный пример, чтобы убедиться, что мы находимся на той же странице:
mix phx.new github_omg
mix ecto.create
mix phx.gen.json Accounts User users name:string
mix ecto.migrate
iex -S mix phx.server
Для репликации вы можете вставлять команды одну за другой и следовать инструкциям, например (phx.gen.json
указывает надобавьте resources "/users", UserController, except: [:new, :edit]
к scope "/api"
в lib/github_omg_web/router.ex
.
. Создается новый проект с тем же именем github_omg
, контекст с именем Accounts
и конечная точка API с именем localhost:4000/api/users
Давайте выполним некорректный запрос с помощью curl
:
curl --write-out '%{http_code}' --silent -X POST -H "Content-Type: application/json" --data "Invalid JSON" --output /dev/null localhost:4000/api/users
Я использую --silent
и --output /dev/null
, чтобы скрыть тело ответа. В режиме разработки он выведет всю страницу с ошибкой Phoenix и захламитвывод. --write-out '%{http_code}
показывает статус http, -H
добавляет заголовки, а --data
- неверный JSON, который мы отправляем.
Вывод будет:
400
, поэтому он выглядиткак Phoenix правильно выводит 400.
В консоли Phoenix мы увидим:
[info] POST /api/users
[debug] ** (Plug.Parsers.ParseError) malformed request, a Jason.DecodeError exception was raised with message "unexpected byte at position 0: 0x49 ('I')"
Таким образом, под капотом выглядит, как Phoenix автоматически преобразует ParseError
в 400. На самом деле этоне то, что волшебство:)
Phoenix вычисляет ошибку, используя протокол Plug.Exception
.В принципе, вы можете выбросить любое исключениеМакрос defexception
позволяет вам прикрепить пользовательские поля внутри исключения.Феникс ищет поле под названием plug_status
.Plug.Parser
определяет ParseError
для возврата 400.
Вернуться к исходному вопросу:
Вы неправильно прочитали ошибку стека.Тестовая структура не пытается кодировать полезную нагрузку.Это ваше приложение пытается его декодировать (и терпит неудачу).Вы можете прочитать трассировку стека в обратном направлении:
- проверяет конечную точку вызова (это уже код вашего приложения)
- анализаторы подключений конечной точки
- этот плагин вызывает исключение
Это означает, что у вас есть два варианта:
- Вы можете вообще пропустить этот тест.Это не является частью логики вашего приложения, и, возможно, не имеет смысла тестировать используемую вами фреймворк.
- Если вы действительно хотите убедиться (потому что, например, вы работаете с конвейером
api
с пользовательскими заглушками)), вместо проверки на 400, вы можете проверить, корректно ли возникает ваше приложение:
assert_raise Plug.Parsers.ParseError, fn ->
conn
|> put_req_header("content-type", "application/json")
|> post(Routes.convert_path(conn, :convert), "invalid JSON")
end
Вы проверяете на 400 в conn явно только в тех случаях, когда вы устанавливаете его явно.