Django中reverse_lazy模拟失效求助:无需目标URL完成测试
问题描述
测试Django用户注册视图UserRegisterView时,希望通过mockreverse_lazy跳过创建user-register-first-success对应的URL和视图,但尝试了两种patch方式都无效,依然抛出NoReverseMatch错误。目前通过临时添加URL解决,求无需创建实际URL的正确mock方案。
相关代码
views.py
# views.py from django.contrib.auth import get_user_model from django.urls import reverse_lazy from django.views import generic from accounts import forms User = get_user_model() class UserRegisterView(generic.FormView): model = User template_name = 'accounts/register_form.html' form_class = forms.UserRegisterForm success_url = reverse_lazy('accounts:user-register-first-success') def form_valid(self, form): form.save() return super().form_valid(form)
test_views.py
# test_views.py from unittest.mock import patch from django.contrib.auth import get_user_model from django.test import TestCase from django.urls import reverse User = get_user_model() class UserRegisterViewTest(TestCase): def setUp(self) -> None: self.url = reverse('accounts:user-register') self.data = { 'email': 'rick.sanchez@test.com', 'password': 'qwe123!@#', 'confirmed_password': 'qwe123!@#', } @patch('accounts.views.reverse_lazy', return_value='mock_url') def test_view_redirects_to_correct_page_POST(self, mock): response = self.client.post(self.url, self.data) self.assertRedirects(response, mock('accounts:user-register-first-success')) @patch('django.urls.reverse_lazy', return_value='mock_url') def test_view_redirects_to_correct_page_POST_(self, mock): response = self.client.post(self.url, self.data) self.assertRedirects(response, mock('accounts:user-register-first-success'))
错误信息
File "/home/branya/Документи/My Projects/Django/hotel/venv/lib/python3.10/site-packages/django/urls/resolvers.py", line 848, in _reverse_with_prefix raise NoReverseMatch(msg) django.urls.exceptions.NoReverseMatch: Reverse for 'user-register-first-success' not found. 'user-register-first-success' is not a valid view function or pattern name.
解决方案
问题根源
UserRegisterView的success_url是类属性,在views模块被导入时就会执行reverse_lazy生成值。而你的测试是在模块导入完成后才patchreverse_lazy,此时success_url已经被赋值为真实的URL解析结果(解析失败就报错),所以mock根本没生效。
三种可行方案
方案1:直接替换视图类的success_url属性
不需要mockreverse_lazy,测试时直接覆盖类属性:
def test_view_redirects_to_correct_page_POST(self): UserRegisterView.success_url = 'mock_url' response = self.client.post(self.url, self.data) self.assertRedirects(response, 'mock_url')
方案2:用patch.object直接mock视图类的success_url
这种方式更简洁,直接针对类属性进行patch:
from unittest.mock import patch class UserRegisterViewTest(TestCase): # ... 其他代码不变 ... @patch.object(UserRegisterView, 'success_url', 'mock_url') def test_view_redirects_to_correct_page_POST(self): response = self.client.post(self.url, self.data) self.assertRedirects(response, 'mock_url')
方案3:在模块导入前patchreverse_lazy(验证调用参数)
如果需要验证reverse_lazy是否被传入了正确的参数,可以在views模块导入前就patchreverse_lazy,确保类属性初始化时使用mock后的函数:
from unittest.mock import patch @patch('django.urls.reverse_lazy', return_value='mock_url') class UserRegisterViewTest(TestCase): @classmethod def setUpClass(cls): # 先patch再导入views模块 super().setUpClass() from accounts import views cls.UserRegisterView = views.UserRegisterView def setUp(self) -> None: self.url = reverse('accounts:user-register') self.data = { 'email': 'rick.sanchez@test.com', 'password': 'qwe123!@#', 'confirmed_password': 'qwe123!@#', } def test_view_redirects_to_correct_page_POST(self, mock_reverse_lazy): response = self.client.post(self.url, self.data) self.assertRedirects(response, 'mock_url') # 验证reverse_lazy的调用参数是否正确 mock_reverse_lazy.assert_called_once_with('accounts:user-register-first-success')
内容的提问来源于stack exchange,提问作者Богдан Тимченко
相关产品推荐
相关产品推荐

