首页 > 解决方案 > 我是否必须做任何事情才能使 Plugs 在测试环境(Elixir / Phoenix)中工作?

问题描述

我有一个基本应用程序并尝试在我的控制器上使用插件。如果请求正文没有“url”参数,它基本上应该返回 400。当我从邮递员发送请求时它工作正常,但它似乎不适用于我的测试。

我是否必须做任何事情才能使其在测试环境中也能正常工作?

  plug :check_url_existence when action in [:create]

  def create(conn, link_params) do
    with {:ok, %Link{} = link} <- Links.create_link(link_params) do
      conn
      |> put_status(:created)
      |> put_resp_header("location", Routes.link_path(conn, :show, link))
      |> render("show.json", link: link)
    end
  end

  defp check_url_existence(conn, _) do
    if is_nil(conn.params["url"]) do
      conn
      |> put_status(:bad_request)
      |> put_view(ShortyWeb.ErrorView)
      |> render("400.json")
    end
    conn
  end

测试:

    test "returns an error without a url", %{ conn: conn } do
      response =
        conn
        |> post("/shorten", %{})
        |> json_response(400)

      assert response["errors"] != %{}
    end

结果:

1) test shortcode generation returns an error without a url (ShortyWeb.LinkControllerTest)
     test/shorty_web/controllers/link_controller_test.exs:58
     ** (RuntimeError) expected response with status 400, got: 422, with body:
     {"errors":{"url":["can't be blank"]}}
     code: |> json_response(400)
     stacktrace:
       (phoenix) lib/phoenix/test/conn_test.ex:373: Phoenix.ConnTest.response/2
       (phoenix) lib/phoenix/test/conn_test.ex:419: Phoenix.ConnTest.json_response/2
       test/shorty_web/controllers/link_controller_test.exs:62: (test)

邮递员结果: https ://prnt.sc/qdy2bo

标签: elixirphoenixplug

解决方案


您的 plug 函数的编写方式是无论如何conn都将返回未更改的内容。

您需要将最后一行移动到一个else块中。此外,该if块可能需要调用halt/1.

否则,它将继续使用该create函数并尝试创建链接,但由于验证问题(url 为空白),它将像现在一样失败并返回 422。

你应该将你的插件重写为类似的东西

defp check_url_existence(conn, _) do
  if is_nil(conn.params["url"]) do
    conn
    |> put_status(:bad_request)
    |> put_view(ShortyWeb.ErrorView)
    |> render("400.json")
    |> halt()
  else
    conn
  end 
end

您还应该考虑按照其他人的建议进行操作,而不必担心解析参数。422 似乎是一个有效的响应代码。

如果你想坚持使用 400 处理程序,因为你试图在这里实现,这里有另一种编写它的方法。

defp check_url_existence(%{params: %{"url" => url}} = conn) when not is_nil(url), do: conn
defp check_url_existence(conn) do
  conn
  |> put_status(:bad_request)
  |> put_view(ShortyWeb.ErrorView)
  |> render("400.json")
  |> halt()
end

为了直接回答您的问题,conn 测试助手会遍历路由器代码,因此应该应用插件。

在某些极端情况下,当您实现自己的帮助程序时,您需要手动调用某些插件函数,但这些可能超出了问题的范围。


推荐阅读