12

I have a python function that returns multiples values. My function:

def myExampleFunction(a,b)
    # here is my code
    return name, number1, number2


def FunctionIWantToTest(self):
    # here is my code
    myName, myNumber1, myNumber2 = self.myExampleFunction(a,b)

I want to give my own values to the returned values from FunctionIWantToTest. So, I'm trying to test the 2nd function with nosetest, but I don't know how to mock the return of myExampleFunction.

I tried this:

def test_mytest(self):
    [...]
    c.myExampleFunction = Mock()
    c.myExampleFunction.side_effect = ["myName", 100, 200]
    [...]

But it doesn't work. When I launch nosetests I read this message:

ValueError: too many values to unpack

Any idea? I use python 2.7.3

matthewbauer
  • 4,314
  • 1
  • 17
  • 22
myg
  • 185
  • 2
  • 2
  • 8
  • [Documentation](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock): If side_effect is an iterable then each call to the mock will return the next value from the iterable. – DreyFax Mar 03 '16 at 14:01
  • I response myself: The code that woks for me: c.myExampleFunction.return_value = "myName", 100, 200 – myg Mar 03 '16 at 14:03
  • This is the same as Daniel's answer so please accept it. This makes it easier for users with a similar problem to recognize, that this answer worked. Answers in comments are hard to find. – DreyFax Mar 03 '16 at 14:16

3 Answers3

22

You need to set the return_value of the mock, not side_effect.

You can do this when you instantiate it:

c.myExampleFunction = Mock(return_value=["myName", 100, 200])
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
9

Just wanted to share how to get this to work with side_effect. I put together a simplified version to showcase how to use side_effect for your use case.

side_effect behaves differently than return_value, where when you provide a side_effect with a list with entries, what you are stating actually is that, each time your mocked method is called it will return each item in the list as its return value. This is actually why you are getting ValueError: too many values to unpack (expected 3), because by doing this:

[1, 2, 3]

You are saying, for each call to my mocked method, return 1, then the next time I call the method, return 2, then return 3.

With that in mind, if you set up your side_effect, like this:

[('stuff1', 'stuff2', 'stuff3')]

What you are now saying, is that, for when you call side_effect, the first item in the list is what will be returned. Which, in effect is:

('stuff1', 'stuff2', 'stuff3')

Alternatively, you can do this:

my_test_foo.side_effect = lambda x, y: (1, 2, 3)

Which mimics out the method you are testing by taking two args and returning the three values it should return.

So, with this in mind, your test can be structured as:

import unittest
from unittest.mock import Mock

from mock import patch
from stuff import FunctionIWantToTest


class MyTest(unittest.TestCase):

    @patch('stuff.myExampleFunction', return_value=Mock())
    def test_mytest(self, m_example_function):
        m_example_function.side_effect = [("stuff1", 100, 200)]
        # m_example_function.side_effect = lambda x, y: ("stuff1", 100, 200)

        a, b, c = FunctionIWantToTest()

if __name__ == '__main__':
    unittest.main()
idjaw
  • 25,487
  • 7
  • 64
  • 83
0

Can do it in a simpler way, like:

@patch('path.to.the.function')
def test_bla(self, mock_func):
    mock_func.return_value = 'return 1', 'return 2', 'return 3'
    ...