How to mock a queryset for use in a for loop in python/Mock
django, mocking, python, unit-testing
Solution
You have to use `iterator` and `MagicMock` which has `__iter__` defined
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()
Problem
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() ``` when run, I get TypeError: 'Mock' object is not iterable I have tried patching ``` @mock.patch('__builtin__.iter') ``` but I just can't seem to get it to work. I haven't succeeded in figuring out what really goes on when the query set "used" by the for-loop. Help is greatly appreciated! [edited with further added example code, after first solution proposal]