Search code examples
pythonunit-testingtestingpytest

Mock from unittest not passed to Django view


def test_student_get(admin_user, some_model_fixture):
    client = Client()
    request_with_cookies = set_cookie(client, admin_user[0])

    with patch('django.shortcuts.get_object_or_404') as mock_get_object_or_404:
        mock_get_object_or_404.side_effect = Http404

        response_from_view = client.get(
            reverse('student.get'),
            HTTP_REFERER=request_with_cookies.request['PATH_INFO'],
            data={'id': some_model_fixture.id},
            follow=True
        )
    assert response_from_view.status_code == 404

So, I'm writing some tests for my Django app, but I faced some problem: I try to mock django.shortcuts.get_object_or_404 func using unittest, it's successfully mocking in test_student_get function, but when my request goes up to view mocked func just disappearing and mock_get_object_or_404 is behaving like usual, like it never been mocked.

My view:

    try:
        value = get_object_or_404(SomeModel,id=id)
    except Http404:
        raise ApiError('Not found any obj', 404)

Also tried @patch decorator, same effect, maybe I'm doing something wrong.


Solution

  • get_object_or_404 performs a query your_model.objects.all() and then filter by the arguments you sent.

    So, to perform a patch you should do something like

    @patch('path.to.your.model.YourModel.objects.all')
    def test_get_object(self, mock_your_model)
        ...
    

    Anyways I would recommend you to use something like

    try:
        YourModel.objects.get(id=<id>)
    except YourModel.DoesNotExist:
        raise ApiError('Not found any obj', 404)