首页 > 解决方案 > 如何测试控制器授权

问题描述

我有一个类似于这个简化代码的控制器:

defmodule Web.UserController do
  use Web, :controller

  alias App.User

  action_fallback Web.FallbackController

  def authorize(conn) do
    # in my code I have somo checks here

    conn
      |> send_resp(403, "")
      |> halt()
  end

  def index(conn, _params) do
    authorize(conn)

    users = User.all
    render(conn, "index.json", users: users)
  end
end
  test "lists all users", %{conn: conn} do
    conn = get(conn, Routes.user_path(conn, :index))
    users = User.all

    assert conn.halted
    assert json_response(conn, 403)
  end

当我用休息客户端检查它时它会返回403,但在测试中它会返回200。我该如何测试它?

标签: elixirphoenix-frameworkphoenix

解决方案


测试很好,你的代码不是。

您的authorize函数返回 a conn,但您从不在index函数上使用它。

当您使用休息客户端请求它时,连接会正确接收

conn
|> send_resp(403, "")

但是在 ExUnit 中,它会得到index返回的结果:render(conn, "index.json", users: users)

由于您没有使用connthatauthorize(conn)返回

我建议快速解决此问题:

defmodule Web.UserController do
  use Web, :controller

  alias App.User

  action_fallback Web.FallbackController

  def authorize(conn) do
    # in my code I have somo checks here

    :not_authorized
  end

  def index(conn, _params) do
    case authorize(conn) do
      :not_authorized -> 
        conn
          |> send_resp(403, "")
          |> halt()      # not necessary since send_resp already does it
      :authorized ->
        users = User.all
        render(conn, "index.json", users: users)
    end
  end
end

更好的解决方案是制作一个用于授权目的的插件,将其添加到路由器中的管道中,如果连接未经授权,它将无法到达您的控制器。


推荐阅读