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

无法为Django密码重置流程编写集成测试的问题解决

解决Django PasswordResetConfirmView测试中密码不更新的问题

我之前也踩过这个Django密码重置测试的坑!你的手动测试正常但单元测试失败,核心原因是没搞清楚PasswordResetConfirmView的工作流程——这个视图必须先通过GET请求完成token验证,之后才能接受POST请求修改密码,而你的测试直接跳过了GET验证步骤。

问题分析

从你给出的redirect_chain就能看出端倪:[('/accounts/reset/token_removed/set-password/', 302)],这说明当你直接POST到带token的URL时,视图其实是把你重定向到了set-password端点,但你跟随重定向后并没有在这个端点提交表单,所以密码修改操作根本没执行。

Django的PasswordResetConfirmView逻辑是这样的:

  1. GET请求带uidb64和token的URL:验证token有效性,生成临时会话,重定向到set-password页面(此时URL中的token被替换成"set-password")。
  2. 只有在set-password端点的POST请求才会真正处理密码修改。

修正后的测试代码

你已经找到了正确的解决方案,这里再把关键步骤解释清楚:

def test_password_reset_ok(self):
    # 1. 请求密码重置
    response = self.myclient.post(PASSWORD_RESET_URL, {"email": VALID_USER_NAME}, follow=True)
    
    # 2. 从邮件中提取重置token和uidb64
    self.assertEqual(len(mail.outbox), 1)
    msg = mail.outbox[0]
    uidb64, token = utils_extract_reset_tokens(msg.body)
    
    # 3. 先发送GET请求完成token验证,初始化会话
    self.myclient.get(PASSWORD_RESET_CONFIRM_URL(uidb64, token), follow=True)
    
    # 4. 向set-password端点POST新密码,完成修改
    response = self.myclient.post(
        PASSWORD_RESET_CONFIRM_URL(uidb64, "set-password"),
        {"new_password1": USER_NEW_PSW, "new_password2": USER_NEW_PSW},
        follow=True
    )
    
    # 验证旧密码失效
    self.assertIsNone(authenticate(username=VALID_USER_NAME,password=USER_OLD_PSW))

关键修改点:

  • 增加了self.myclient.get(...)步骤:让视图完成token验证,建立必要的会话状态,确保后续的POST请求能被正确处理。
  • POST请求的URL把原token替换成了"set-password":这是视图验证后重定向到的端点,只有这里的POST才会触发密码更新逻辑。

这样修改后,测试就能和手动流程保持一致,密码修改操作会被正确执行,断言也能通过了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:34:44