[TIP] Using Mock to patch an iterator / generator?

Michael Foord michael at voidspace.org.uk
Tue Jun 14 04:52:18 PDT 2011


On 13/06/2011 15:57, Michael Foord wrote:
> On 11/06/2011 10:35, Michael Foord wrote:
>> On 10/06/2011 00:08, Andrew Hammond wrote:
>>> I have a class that looks like
>>>
>>> class Foo(object):
>>>     def iter(descending=False):
>>>         for r in something_iterable:
>>>             yield r
>>>
>>>
>> Hey Andrew,
>>
>> Because of the use of yield, your iter is a generator and not a 
>> normal method. Mocking a generator (or any iterable) can be done with 
>> the MagicMock (in mock 0.7).
>>
>> You can then configure the return values using something similar to this:
>>
>> mock = MagicMock()
>>
>> values = [1, 2, 3]
>> mock.iter.__iter__.side_effect = lambda: values.pop()
>>
>
> Actually, this isn't quite correct (my apologies).
>
> Foo.iter *returns* a generator when called. It isn't directly a 
> generator. Also the __iter__ method should return the iterator.
>
> >>> values = [1, 2, 3]
> >>> mock_foo = MagicMock()
> >>> mock_foo.iter.return_value.__iter__.return_value = iter(values)
> >>> list(mock_foo.iter())
>     [1, 2, 3]
>

Heh, actually you could probably just do:

     mock_foo.iter.return_value = iter(values)

But there you go... :-)

Michael

> I'm adding this as a recipe to the "examples" page as I got it wrong 
> on the first attempt... :-)
>
> Michael
>> All the best,
>>
>> Michael Foord
>>
>>> I would like to mock the class and patch Foo.iter. I have tried a 
>>> number of things without luck.
>>>
>>> class TestFoo(PatchedTestCase):
>>>     _partitions = []
>>>
>>>     def partitions(self):
>>>         for p in self._partitions:
>>>             yield p
>>>
>>>     def postSetUpPreRun(self):
>>>         self._partitions = [ 1, 2, 3, 4  ]
>>>         rw = Mock(spec=Foo)
>>>         self.mock_RollingWindow = rw
>>>         rw.iter = Mock()
>>>         rw.iter.side_effect = self.partitions
>>>
>>> This is following the pattern I've used for other methods, but 
>>> doesn't work for an iterator... so, what is the proper approach please?
>>>
>>> Andrew
>>>
>>>
>>> _______________________________________________
>>> testing-in-python mailing list
>>> testing-in-python at lists.idyll.org
>>> http://lists.idyll.org/listinfo/testing-in-python
>>
>>
>> -- 
>> http://www.voidspace.org.uk/
>>
>> May you do good and not evil
>> May you find forgiveness for yourself and forgive others
>> May you share freely, never taking more than you give.
>> -- the sqlite blessinghttp://www.sqlite.org/different.html
>>
>>
>> _______________________________________________
>> testing-in-python mailing list
>> testing-in-python at lists.idyll.org
>> http://lists.idyll.org/listinfo/testing-in-python
>
>
> -- 
> http://www.voidspace.org.uk/
>
> May you do good and not evil
> May you find forgiveness for yourself and forgive others
> May you share freely, never taking more than you give.
> -- the sqlite blessinghttp://www.sqlite.org/different.html
>
>
> _______________________________________________
> testing-in-python mailing list
> testing-in-python at lists.idyll.org
> http://lists.idyll.org/listinfo/testing-in-python


-- 
http://www.voidspace.org.uk/

May you do good and not evil
May you find forgiveness for yourself and forgive others
May you share freely, never taking more than you give.
-- the sqlite blessing http://www.sqlite.org/different.html

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/testing-in-python/attachments/20110614/022775b9/attachment.html>


More information about the testing-in-python mailing list