使用Guardian进行控制器测试:已认证路由请求授权问题
我来帮你搞定带认证的API控制器测试问题!看起来你已经有了基础的测试结构,但还没处理请求的授权逻辑,下面分步骤给你调整方案:
第一步:在Setup中添加认证逻辑
Phoenix的setup块会在每个测试用例执行前运行,正好用来处理认证,这样每个测试拿到的conn都是已经授权过的。根据你的认证方式(JWT/Session/API Key),选择对应的实现:
情况1:JWT认证(最常见的API认证方式)
假设你有用户创建和JWT生成的函数,修改setup如下:
# 先定义测试用的用户属性(放在测试模块顶部) @user_attrs %{email: "test_league_user@example.com", password: "secure_password123"} @valid_attrs %{name: "Test Premier League", description: "A test football league"} setup %{conn: conn} do # 1. 创建测试用户 {:ok, user} = YourApp.Accounts.create_user(@user_attrs) # 2. 生成用户的JWT token(替换成你项目里的token生成函数) token = YourApp.Accounts.generate_auth_token(user) # 3. 给conn设置必要的请求头:Accept + Authorization Bearer token authorized_conn = conn |> put_req_header("accept", "application/json") |> put_req_header("authorization", "Bearer #{token}") {:ok, conn: authorized_conn, user: user} end
情况2:Session认证(适合前后端同构的Phoenix应用)
如果你的认证是基于Session的,就先模拟登录请求拿到带认证Session的conn:
setup %{conn: conn} do {:ok, user} = YourApp.Accounts.create_user(@user_attrs) # 模拟登录请求,获取认证后的conn authorized_conn = conn |> put_req_header("accept", "application/json") |> post(YourApp.Router.Helpers.session_path(conn, :create), user: %{email: user.email, password: @user_attrs.password}) |> recycle() # 重置conn状态,保留Session信息 {:ok, conn: authorized_conn, user: user} end
情况3:API Key认证
如果是用固定API Key的简单认证,直接在请求头里加Key即可:
setup %{conn: conn} do authorized_conn = conn |> put_req_header("accept", "application/json") |> put_req_header("x-api-key", "your_test_api_key_here") {:ok, conn: authorized_conn} end
第二步:修改你的测试用例
现在每个测试拿到的conn已经是授权过的了,直接用它发起请求就行:
test "creates and renders resource when data is valid", %{conn: conn} do conn = post(conn, YourApp.Router.Helpers.league_path(conn, :create), league: @valid_attrs) # 断言返回201创建成功状态码 assert json_response(conn, 201)["data"]["name"] == @valid_attrs.name # 可以根据你的API返回结构添加更多断言 end
额外:测试未认证的场景
别忘了测试未授权请求的情况,确保你的认证拦截逻辑正常:
test "returns 401 Unauthorized when not authenticated", %{conn: conn} do # 创建一个未认证的干净conn unauthed_conn = put_req_header(conn, "accept", "application/json") conn = post(unauthed_conn, YourApp.Router.Helpers.league_path(conn, :create), league: @valid_attrs) assert json_response(conn, 401)["error"] == "Unauthorized" end
这样就能完整覆盖认证路由的控制器测试啦!
内容的提问来源于stack exchange,提问作者Bitwise
相关产品推荐
相关产品推荐

