【问题标题】:How do you set the body of a POST request in an Elixir Plug test?如何在 Elixir Plug 测试中设置 POST 请求的主体?
【发布时间】:2017-07-18 07:05:56
【问题描述】:

使用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 设置内容类型标头。

【问题讨论】:

    标签: elixir


    【解决方案1】:

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

    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中。

    【讨论】:

      猜你喜欢
      • 2018-01-30
      • 1970-01-01
      • 1970-01-01
      • 2020-12-21
      • 1970-01-01
      • 1970-01-01
      • 2018-06-10
      • 1970-01-01
      • 2021-03-03
      相关资源
      最近更新 更多