如何在Django测试中获取RequestFactory抛出异常后的messages消息?
问题描述
使用Mock测试Django基于类的视图SignUpView时,已模拟create_user方法抛出异常,且验证了视图捕获异常后的重定向行为正常,但无法获取视图创建的错误消息以完成断言验证,请问如何获取该消息并与指定内容对比?
视图代码
CustomUser = get_user_model() class SignUpView(FormView): template_name = 'accounts/signup.html' form_class = SignUpForm def form_valid(self, form): try: self.user = CustomUser.objects.filter(email=form.cleaned_data['email']).first() if not self.user: self.user = CustomUser.objects.create_user( email=form.cleaned_data['email'], full_name=form.cleaned_data['full_name'], password=form.cleaned_data['password'], is_verified=False ) else: if self.user.is_verified: self.send_reminder() return super().form_valid(form) self.send_code() except: messages.error(self.request, _('Something went wrong, please try to register again')) return redirect(reverse('accounts:signup')) return super().form_valid(form)
测试代码(当前状态)
class SignUpViewTest(TestCase): def setUp(self): self.factory = RequestFactory() def test_database_fail(self): with patch.object(CustomUserManager, 'create_user') as mock_method: mock_method.side_effect = Exception(ValueError) view = SignUpView.as_view() url = reverse('accounts:signup') data = {'email': 'test@test.com', 'full_name': 'Test Tester', 'password': 'Abnm1234'} request = self.factory.post(url, data) setattr(request, 'session', 'session') messages = FallbackStorage(request) request._messages = messages response = view(request) self.assertEqual(response.status_code, 302) self.assertEqual(response.url, '/accounts/signup/')
解决方案
你已经在测试中初始化了FallbackStorage处理消息,只需添加以下步骤即可获取并断言消息:
- 首先导入Django的消息获取工具:
from django.contrib.messages import get_messages
- 在获取
response之后,调用get_messages(request)获取存储的消息列表,然后对消息的内容和级别进行断言:
# 转换为列表便于操作 message_list = list(get_messages(request)) # 断言存在且仅存在一条消息 self.assertEqual(len(message_list), 1) # 断言消息内容匹配 self.assertEqual(message_list[0].message, 'Something went wrong, please try to register again') # 可选:断言消息级别为错误类型 self.assertEqual(message_list[0].level, messages.ERROR)
完整的测试方法修改后如下:
class SignUpViewTest(TestCase): def setUp(self): self.factory = RequestFactory() def test_database_fail(self): from django.contrib.messages import get_messages import messages with patch.object(CustomUserManager, 'create_user') as mock_method: mock_method.side_effect = Exception(ValueError) view = SignUpView.as_view() url = reverse('accounts:signup') data = {'email': 'test@test.com', 'full_name': 'Test Tester', 'password': 'Abnm1234'} request = self.factory.post(url, data) setattr(request, 'session', 'session') messages_storage = FallbackStorage(request) request._messages = messages_storage response = view(request) self.assertEqual(response.status_code, 302) self.assertEqual(response.url, '/accounts/signup/') # 消息断言部分 message_list = list(get_messages(request)) self.assertEqual(len(message_list), 1) self.assertEqual(message_list[0].message, 'Something went wrong, please try to register again') self.assertEqual(message_list[0].level, messages.ERROR)
注意:如果视图中使用了ugettext_lazy(即_()是懒加载翻译),需要将消息转换为字符串后再断言,比如str(message_list[0].message)。
内容的提问来源于stack exchange,提问作者Radial
相关产品推荐
相关产品推荐

