Search code examples
pythondjangounit-testingdjango-querysetdjango-testing

Django unit test mock queryset from related object


I have the following function:

import unittest
from unittest import mock


def get_payments(order):
    return order.payments.filter(status='complete').order_by('-date_added)

I want to mock the filter method and the order_by to check the arguments with which are called.

I tried:

class TestPayments(unittest.TestCase):
     @mock.patch('path.Order.payments.filter.order_by')
     @mock.patch('path.Order.payments.filter')
     def test_get_payments(self, mock1, mock2):
        mock1.assert_called_with(status='complete')
        mock2.assert_called_with('-date_added')

Another mock I tried:

@mock.patch('path.Payment.objects.filter.order_by')
@mock.patch('path.Payment.objects.filter')

@mock.patch('path.Order.payments.objects.filter.order_by')
@mock.patch('path.Order.payments.objects.filter')

In last two mocks I have an error that path.Order does not exists. I already used a direct mock for a query like Payment.objects.filter() and is working, but starting from a related model like Order I failed.

The relationship between Order and Payment is how you would expect, one to many.


Solution

  • by mocking objects I resolved this.

        order = MagicMock(side_effect=Order())
        order.payments.filter.return_value = MagicMock(side_effect=Payment.objects.filter(id=0))
        order.payments.filter.return_value.order_by.return_value = [Payment()]
    
        order.payments.filter.assert_called_with(status='complete')
        order.payments.filter.return_value.order_by.assert_called_with('-date_updated')