使用ConnTest的帖子发送无效的JSON

时间:2019-02-13 23:40:20

标签: elixir phoenix-framework

我正在尝试测试端点是否在无效JSON上返回400。如果我做这样的事情:

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 :(得分:1)

我创建了一个最小的示例,以确保我们在同一页面上:

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,名为localhost:4000/api/users的上下文和名为curl的api端点的新项目

让我们用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--write-out '%{http_code}隐藏响应正文。在开发模式下,它将输出整个Phoenix错误网页,并使输出混乱。 -H显示http状态,--data添加标头,400 是我们发送的无效JSON。

输出将是:

[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可以正确输出400。

在Phoenix控制台中,我们将看到:

ParseError

因此,看起来Phoenix会自动将Plug.Exception转换为400。实际上,这并不是那么神奇:)

Phoenix使用defexception协议计算错误。基本上,您可以抛出任何您喜欢的异常。 plug_status宏允许您在异常内附加自定义字段。 Phoenix寻找一个名为Plug.Parser的字段。 ParseError定义api返回400。

回到原始问题:

您误读了堆栈错误。测试框架不会尝试对有效载荷进行编码。这是您的应用尝试对其进行解码(并且失败)。您可以向后读取堆栈跟踪:

  • 测试呼叫端点(这已经是您的应用代码)
  • 端点调用插件解析器
  • 此插件引发异常

这意味着您有两个选择:

  1. 您可以完全跳过该测试。它不是您的应用程序逻辑的一部分,测试您使用的框架可能没有意义。
  2. 如果您确实要确保(例如,由于您正在使用带有自定义插件的 assert_raise Plug.Parsers.ParseError, fn -> conn |> put_req_header("content-type", "application/json") |> post(Routes.convert_path(conn, :convert), "invalid JSON") end 管道弄乱了),而不是检查400,则可以检查您的应用是否出现正确的错误:
/usr/local/bin/ea-php56 /home/username/domain_path/path/to/cron/script

仅在显式设置的情况下,才显式测试conn中的400。