Отправка недействительного JSON с постом ConnTest - PullRequest
0 голосов
/ 14 февраля 2019

Я пытаюсь проверить, что моя конечная точка возвращает 400 при неверном JSON.Если я сделаю что-то вроде этого:

response = conn
  |> put_req_header("content-type", "application/json")
  |> post(Routes.convert_path(conn, :convert), "invalid JSON")

, я получу Jason.DecodeError, потому что он пытается закодировать мою строку.Как я могу получить это, чтобы не закодировать это?Глядя на документы, кажется, что это невозможно:

post(conn, path_or_action, params_or_body \\ nil)

Есть ли другой способ сделать то, что я пытаюсь сделать?

 test/github_omg_web/controllers/convert_controller_test.exs:36
 ** (Plug.Parsers.ParseError) malformed request, a Jason.DecodeError exception was raised with message "unexpected byte at position 0: 0x61 ('a')"
 code: |> post(Routes.convert_path(conn, :convert), "asdf")
 stacktrace:
   (plug) lib/plug/parsers/json.ex:97: Plug.Parsers.JSON.decode/2
   (plug) lib/plug/parsers.ex:271: Plug.Parsers.reduce/7
   (github_omg) lib/github_omg_web/endpoint.ex:1: GithubOmgWeb.Endpoint.plug_builder_call/2
   (github_omg) lib/github_omg_web/endpoint.ex:1: GithubOmgWeb.Endpoint.call/2
   (phoenix) lib/phoenix/test/conn_test.ex:235: Phoenix.ConnTest.dispatch/5
   test/github_omg_web/controllers/convert_controller_test.exs:40: (test)

1 Ответ

0 голосов
/ 15 февраля 2019

Я создал минимальный пример, чтобы убедиться, что мы находимся на той же странице:

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.

Вернуться к исходному вопросу:

Вы неправильно прочитали ошибку стека.Тестовая структура не пытается кодировать полезную нагрузку.Это ваше приложение пытается его декодировать (и терпит неудачу).Вы можете прочитать трассировку стека в обратном направлении:

  • проверяет конечную точку вызова (это уже код вашего приложения)
  • анализаторы подключений конечной точки
  • этот плагин вызывает исключение

Это означает, что у вас есть два варианта:

  1. Вы можете вообще пропустить этот тест.Это не является частью логики вашего приложения, и, возможно, не имеет смысла тестировать используемую вами фреймворк.
  2. Если вы действительно хотите убедиться (потому что, например, вы работаете с конвейером 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 явно только в тех случаях, когда вы устанавливаете его явно.

...