Home > other >  Raise an exception using mock when a specific Django model is called
Raise an exception using mock when a specific Django model is called

Time:11-25

I have a class based view inheriting from FormView with an overridden form_valid() method that I would like to test.

As you can see, form_valid() is required to access the CustomUser model which is wrapped with a try and except.

What I am trying to do is raise an exception whenever create_user is called, but I am having no success.

The CustomUser has been created in the usual way via a CustomUserManager with a create_user method.


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)

What I have tried:

  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': '[email protected]', 'full_name': 'Test Tester', 'password': 'Abnm1234'}
        request = self.factory.post(url, data)
        request.session = {}
        request.messages = {}
        response = view(request)

and ..

  def test_database_fail(self):
       
        CustomUser = Mock()

        CustomUser.objects.create_user.side_effect = CustomUser.ValueError

        view = SignUpView.as_view()
        url = reverse('accounts:signup')
        data = {'email': '[email protected]', 'full_name': 'Test Tester', 'password': 'Abnm1234'}
        request = self.factory.post(url, data)
        request.session = {}
        request.messages = {}
        response = view(request)

In both cases no exception is triggered.

My question is, how can I raise an exception whenever create_user is called using mock?

CodePudding user response:

You need to write the whole test under mock.patch context manager. Otherwise once with statement is finished, mock doesn't work anymore and has no effect. Try this:

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': '[email protected]', 'full_name': 'Test Tester', 'password': 'Abnm1234'}
        request = self.factory.post(url, data)
        request.session = {}
        request.messages = {}
        response = view(request)

Also note that you can specify side_effect directly in patch.object method:

with patch.object(CustomUserManager, 'create_user', side_effect=Exception):
    # rest of your code
  • Related