How to deride a set of queries for use in a for loop in python / Mock

I am writing some unit tests and want to use Mock.

Given the following code:

# the 'real' query set is a Django database model
# qs = SomeDjangoModel.objects.filter(name='some_name')
qs = mock.Mock()
qs.filter.return_value = qs
item = mock.Mock()
item.do_work.return_value = "Some text"
qs.iter.return_value = iter([item])
# below is the code I want to test..
qs = qs.filter(name='some name')
qs = qs.filter(valid_from__lte=Timezone.now())
for obj in qs:
    obj.do_work()

at startup i get

TypeError: "Mock" object is not iterable

I tried the fix

@mock.patch('__builtin__.iter')

but I just can't get it to work. I was not able to figure out what really happens when the query sets the "used" for the loop.

Help is greatly appreciated!

[edited with added sample code, after proposing the first solution]

+3
source share
3 answers

You must use iteratorand MagicMockwhich has a __iter__certain

from unittest.mock import Mock, MagicMock
from datetime import datetime

qs = MagicMock()
qs.filter.return_value = qs
item = Mock()
item.do_work.return_value = "Some text"
qs.iterator.return_value = iter([item])
# below is the code I want to test..
qs = qs.filter(name='some name')
qs = qs.filter(valid_from__lte=datetime.now())
for obj in qs:
    obj.do_work()
+2
source

QuerySet , . :

something.return_value = [item]

something - , QuerySet. :

MyModel.objects.filter.return_value = [item]

, QuerySet.

+1

My colleague helped me solve this problem. I need the following code.

  def the_iter(self):
        return iter(self.my_test_list)

    def test_my_code(self):
        qs = mock.Mock()
        qs.filter.return_value = qs
        the_item = mock.Mock()
        the_item.do_work.return_value = "Some text"
        self.my_test_list = [the_item]
        qs.__iter__ = mock.Mock(side_effect=self.the_iter)

        # below is the code I want to test..
        qs = qs.filter(name='some name')
        qs = qs.filter(colour='Yellow')
        for obj in qs:
            print obj.do_work()
+1
source

All Articles