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

如何在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处理消息,只需添加以下步骤即可获取并断言消息:

  1. 首先导入Django的消息获取工具:
from django.contrib.messages import get_messages
  1. 在获取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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:25:19