I have a controller similar to this simplified code:
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
When I check it with rest client it return 403
but in the test it returns 200
. How I can test it?
The test is good, your code is not.
your authorize
function return a conn
, but you never use it on the index
function.
When you request it with a rest client, the connection receives correctly the
conn
|> send_resp(403, "")
But in ExUnit, it gets what index
returns : render(conn, "index.json", users: users)
Since you haven't use the conn
that authorize(conn)
returns
My suggestion to fix this issue rapidly :
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
A better solution would be to make a Plug for authorization purpose, add it to a pipeline in your router, it will not reach your controller if the connection is not authorized.