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
In Python, you can return multiple values by simply return them separated by commas. In Python, comma-separated values are considered tuples without parentheses, except where required by syntax. For this reason, the function in the above example returns a tuple with each value as an element.
So what is the difference between them? MagicMock is a subclass of Mock . It contains all magic methods pre-created and ready to use (e.g. __str__ , __len__ , etc.). Therefore, you should use MagicMock when you need magic methods, and Mock if you don't need them.
How do we mock in Python? Mocking in Python is done by using patch to hijack an API function or object creation call. When patch intercepts a call, it returns a MagicMock object by default. By setting properties on the MagicMock object, you can mock the API call to return any value you want or raise an Exception .
side_effect: A function to be called whenever the Mock is called. See the side_effect attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns DEFAULT , the return value of this function is used as the return value.
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()
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])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With