Rafay
Rafay

Reputation: 6188

How to mock chained methods on Django models

I am trying to do something like this to mock methods on a Django model using the Python mock library:

# file: tasks.py
def delete_ads(user):    
    # works fine and return a list of 4 MagicMock objects
    ads = Classifieds.objects.filter(
        user=user
    )

# file: tests.py
def test_delete_ads():
    return_list = [MagicMock(name='1'), MagicMock(name='2'), MagicMock(name='3'), MagicMock(name='4')]

    with patch('user.tasks.Classifieds') as classified_mock:
        classified_mock.objects.filter.return_value = return_value

The above code works fine but starts returning a single MagicMock object after I change my code to this:

# file: tasks.py
def delete_ads(user):    
    # works fine and return a list of 4 MagicMock objects
    ads = Classifieds.objects.filter(
        user=user
    ).order_by('-added')

# file: tests.py
def test_delete_ads():
    return_list = [MagicMock(name='1'), MagicMock(name='2'), MagicMock(name='3'), MagicMock(name='4')]

    with patch('user.tasks.Classifieds') as classified_mock:
        classified_mock.objects.filter.order_by.return_value = return_value

Is there anyway that I can do this correctly even when I am chaining method calls on Django models?

Upvotes: 0

Views: 822

Answers (1)

Dunes
Dunes

Reputation: 40778

When mocking the return value of a mocked function you must mock the function as it would be called in the code. parent.child creates an attribute called child on the parent mock. Whereas, parent().child creates an attribute called child on the mocked return value of parent().

Upvotes: 1

Related Questions