如何在Elixir Plug测试中设置POST请求的主体?

时间:2017-07-17 21:41:39

标签: elixir

使用Plug.Test.conn,设置请求正文似乎不起作用。

这是插件:

defmodule MyPlug do
  import Plug.Conn

  def init(_), do: nil

  def call(conn, _) do
    {:ok, body, _conn} = read_body(conn)
    send_resp(conn, 200, "body: #{body}")
  end
end

使用curl

$ curl -X POST -d foo=bar http://localhost:4000/
body: foo=bar

使用Plug.Test

defmodule MyTest do
  use ExUnit.Case, async: false
  use Plug.Test

  test "POST request" do
    conn = conn(:post, "/", %{foo: "bar"})
           |> MyPlug.call(%{})
    assert conn.resp_body == "body: foo=bar"
  end
end

失败:

  1) test POST request (MyPlugTest)
     test/my_plug_test.exs:28
     Assertion with == failed
     code:  conn.resp_body() == "body: foo=bar"
     left:  "body: "
     right: "body: foo=bar"

我还尝试传递字符串并根据docs设置内容类型标题。

1 个答案:

答案 0 :(得分:5)

在传递给Poison.encode!之前,使用conn将正文转换为二进制文件:

defmodule MyPlug do
  import Plug.Conn

  def init(_), do: nil

  def call(conn, _) do
    {:ok, body, _conn} = read_body(conn)
    send_resp(conn, 200, "body: #{body}")
  end
end

defmodule MyTest do
  use ExUnit.Case
  use Plug.Test

  test "POST request" do
    conn = conn(:post, "/", Poison.encode!(%{foo: "bar"}))
           |> MyPlug.call(%{})
    assert conn.resp_body == ~S(body: {"foo":"bar"})
  end
end

但是Plug.Conn.read_body只能使用一次,之后它会丢弃数据。因此,您可能希望使用Plug.Parsers来解析管道中的主体:

plug Plug.Parsers,
  parsers: [:urlencoded, :multipart, :json],
  pass: ["*/*"],
  json_decoder: Poison

解析后,正文可以在conn.body_params中使用,并合并到conn.params

相关问题