You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Phoenix控制器测试丢失current_user会话问题求助

解决Phoenix测试中登录会话状态丢失的问题

我一眼就看出问题出在哪了——你现在的setup只是手动给初始conn assign 了current_user,但这没法在测试的多个请求之间保留会话状态!原因很简单:Phoenix里每次发起测试请求(比如get/2、post/2)都会生成一个全新的conn对象,而且你的认证逻辑大概率是从**会话(session)**中读取用户身份,而不是直接依赖conn.assigns里的值。手动assign的current_user不会被自动带入新的请求conn,自然就出现了会话丢失的情况。

修正你的Setup代码

你需要在setup里模拟真实的登录流程,把用户身份存入会话,让认证中间件能在后续请求中自动识别用户。这里分两种常见情况给出解决方案:

情况1:基于Session的简单认证

如果你的认证是通过会话中的:user_id来获取用户的,修改setup如下:

setup %{conn: conn} = config do
  if username = config[:login_as] do
    user = insert_user(username: username)
    # 将用户ID存入会话,并刷新会话确保生效
    conn = conn
           |> put_session(:user_id, user.id)
           |> configure_session(renew: true)
    {:ok, conn: conn, user: user}
  else
    :ok
  end
end

情况2:使用Guardian等认证库

如果项目用了Guardian这类JWT/会话认证库,直接用库提供的方法来设置登录状态:

setup %{conn: conn} = config do
  if username = config[:login_as] do
    user = insert_user(username: username)
    # 用Guardian的Plug方法设置登录会话
    conn = Guardian.Plug.sign_in(conn, user)
    {:ok, conn: conn, user: user}
  else
    :ok
  end
end

测试中的关键注意点

在测试用例里,每次请求后一定要使用返回的新conn发起下一个请求,这样会话状态才会被持续保留:

test "登录后访问多个页面", %{conn: conn, user: user} do
  # 第一次请求,获取带会话的新conn
  conn = get(conn, "/dashboard")
  assert html_response(conn, 200) =~ "欢迎回来,#{user.username}"
  
  # 用新的conn发起下一个请求,会话状态会保留
  conn = get(conn, "/profile")
  assert html_response(conn, 200) =~ "个人资料"
end

这样修改后,无论测试里有多少个断言和请求,登录状态都能稳定保持啦!

内容的提问来源于stack exchange,提问作者thyago stall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:55:17