带LoginRequiredMixin的Django登出API匿名用户测试问题
问题分析
你的LogoutView继承了LoginRequiredMixin,未登录用户访问时,这个Mixin会自动重定向到登录页,并且在URL后带上?next=参数记录原请求地址。所以你直接用assertRedirects(response, reverse('login'))会失败,因为实际重定向的URL带了查询参数,和你预期的纯登录URL不匹配。
解决方法
下面给你几个可行的测试修改方案,任选其一即可:
方案1:只验证重定向的路径部分(推荐)
通过解析URL拆分路径和查询参数,只对比登录页的路径,忽略next参数,同时可以额外验证next参数是否正确指向原登出URL:
@pytest.mark.django_db def test_user_logout_unauthenticated_user(client): url = reverse('logout') response = client.get(url) assert response.status_code == 302 # 解析重定向URL,拆分路径和查询参数 from urllib.parse import urlparse, parse_qs redirect_parsed = urlparse(response.url) # 验证重定向到登录页的路径 assert redirect_parsed.path == reverse('login') # 可选:验证next参数是否正确指向原登出URL assert parse_qs(redirect_parsed.query)['next'] == [url]
方案2:直接构造带next参数的预期URL
完全匹配实际的重定向地址,适合需要严格验证完整URL的场景:
@pytest.mark.django_db def test_user_logout_unauthenticated_user(client): url = reverse('logout') response = client.get(url) assert response.status_code == 302 # 构造带next参数的预期登录URL expected_login_url = f"{reverse('login')}?next={url}" assertRedirects(response, expected_login_url)
方案3:检查Location头是否以登录URL开头
最简单的方式,只要重定向的目标路径是登录页就通过:
@pytest.mark.django_db def test_user_logout_unauthenticated_user(client): url = reverse('logout') response = client.get(url) assert response.status_code == 302 assert response['Location'].startswith(reverse('login'))
另外注意你的测试用例名称test_user_logout_logged_in_user和测试场景不符,建议改成test_user_logout_unauthenticated_user,更贴合“未登录用户无法访问登出API”的测试意图。
内容的提问来源于stack exchange,提问作者Parth
相关产品推荐
相关产品推荐

