Skip to content

Instantly share code, notes, and snippets.

@vpetro
Created August 26, 2011 18:10
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save vpetro/1174019 to your computer and use it in GitHub Desktop.
Save vpetro/1174019 to your computer and use it in GitHub Desktop.
Return multiple items from a mocked function with Python's mock.
import mock
def returnList(items):
def func():
for item in items:
yield item
yield mock.DEFAULT
generator = func()
def effect(*args, **kwargs):
return generator.next()
return effect
m = mock.Mock()
m.side_effect = returnList([1,2,3])
for i in ['a', 'b', 'c']:
print i, m()
@vpetro
Copy link
Author

vpetro commented Aug 26, 2011

It is also possible to do the same using the code below:

return_values = [1,2,3]
call_values = [1,2,3]

m2 = mock.Mock()
m2.side_effect = lambda: return_values.pop()
m2.return_value = lambda: call_values.pop()
for i in ['a', 'b', 'c']:
    print i, m2(), m2.return_value()

@vpetro
Copy link
Author

vpetro commented Aug 26, 2011

another way of doing the same thing

return_values = [1,2,3]

def f():
    m2.return_value = return_values[m2.call_count-1]
    return return_values[m2.call_count-1]

m2 = mock.Mock()
m2.side_effect = f

for i in ['a', 'b', 'c']:
    print i, m2(), m2.return_value

@jtpereyda
Copy link

jtpereyda commented Jun 17, 2016

Your main example rewritten to be Python 2 and 3 compatible:

try:
    import mock
except ImportError:
    import unittest.mock as mock


def return_list(items):
    def func():
        for item in items:
            yield item
        yield mock.DEFAULT

    generator = func()

    def effect(*args, **kwargs):
        return next(generator)

    return effect


m = mock.Mock()
m.side_effect = return_list([1, 2, 3])
for i in ['a', 'b', 'c']:
    print(i, m())

@jtpereyda
Copy link

jtpereyda commented Jun 17, 2016

Thanks for this gist, vpetro! Very helpful. You can use iter to simplify a bit:

try:
    import mock
except ImportError:
    import unittest.mock as mock


def return_list(items):
    def func():
        return iter(items)

    generator = func()

    def effect(*args, **kwargs):
        return next(generator)

    return effect


m = mock.Mock()
m.side_effect = return_list([1, 2, 3]) 
for i in ['a', 'b', 'c']:
    print(i, m())

@jtpereyda
Copy link

Turns out you can also just set a side effect to any iterable, including a list:

m = mock.Mock()
m.side_effect = [1, 2, 3]
for i in ['a', 'b', 'c']:
    print(i, m())

http://stackoverflow.com/questions/24897145/python-mock-multiple-return-values

@Arnie97
Copy link

Arnie97 commented Apr 23, 2018

Thanks for your great ideas, vpetro.
By the way, you can always use return_values.pop instead of lambda: return_values.pop().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment