Elixir 使用ConnTest'发送无效的JSON;s柱

Elixir 使用ConnTest'发送无效的JSON;s柱,elixir,phoenix-framework,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(con

我试图测试我的端点是否在无效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)

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

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
指示添加
资源/users“、UserController,除了:[:new,:edit]
范围/api”
中的
lib/github\u omg\u web/router.ex

这是一个新创建的项目,具有相同的名称
github\u 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
隐藏响应正文。在dev模式下,它将输出整个Phoenix错误网页,并使输出混乱。
--write out“{http\u code}
显示http状态,
-H
添加标题,
--data
是我们发送的无效JSON

输出将是:

400
看起来凤凰号输出的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')"
所以它看起来像是引擎盖下的凤凰自动将
ParseError
转换成400。实际上,它并没有那么神奇:)

Phoenix使用
Plug.Exception
协议计算错误。基本上,你可以抛出任何你喜欢的异常
defexception
宏允许您在异常中附加自定义字段。Phoenix查找名为
plug\u status
的字段
Plug.Parser
定义
ParseError
返回400

回到原来的问题:

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

  • 测试调用端点(这已经是您的应用程序代码)
  • 端点调用插件解析器
  • 此插件引发异常
这意味着您有两个选择:

  • 你完全可以跳过那个测试。它不是应用程序逻辑的一部分,测试您正在使用的框架可能没有意义
  • 如果您确实想确保(例如,您正在使用自定义插件处理
    api
    管道),而不是检查400,您可以检查您的应用程序是否出现了正确的错误:

  • 只有在显式设置的情况下,才能在conn中显式测试400。

    您能公布准确的错误吗?我不确定测试是否尝试编码。我相信这是你的应用程序试图解码。它可能是其中一个插头。如果尝试将此端点与
    curl
    一起使用,会发生什么情况?@tkowal问题不在于传入的请求。它正在发送它。添加stacktrace
        assert_raise Plug.Parsers.ParseError, fn ->
          conn
          |> put_req_header("content-type", "application/json")
          |> post(Routes.convert_path(conn, :convert), "invalid JSON")
        end