I'm trying to use Mock, to simulate a function in python. Here is my code:
resp, content = request(...)
The request() function needs to return two values. Here's what I tried:
with patch("syncdatetime.py") as sync_mock: sync_mock.request.return_value = [obj, '']
But when I run the test, I get the error "Mock object is not iterable." The request function returns an object of type Mock instead of a list. How can I patch the request function so that it returns a list?
So to get it to work three methods need to be mocked: Mock the iterable's (the set) iterator() method to return a mock iterator. Mock the iterator's hasNext() method to return true N times followed by false where N is the number of values that you want the iterator to return.
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.
MagicMock. MagicMock objects provide a simple mocking interface that allows you to set the return value or other behavior of the function or object creation call that you patched. This allows you to fully define the behavior of the call and avoid creating real objects, which can be onerous.
Mock vs. 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.
I suspect that your problem is that you are not using the instance of mock that you think you are. By default an instance of Mock returns a Mock when called.
>>> m = mock.Mock() >>> type(m()) <class 'mock.mock.Mock'>
It looks like your call to request
is returning a Mock because the return_value
has not been initialized which means that resp, content = request()
is trying to unpack a Mock object.
>>> m = mock.Mock() >>> (a, b) = m() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'Mock' object is not iterable
You shouldn't need to use side_effect
to return a list. Assigning return_value
should work.
>>> m = mock.Mock() >>> m.return_value = ['a', 'b'] >>> (a, b) = m() >>> a 'a' >>> b 'b'
Note of disclosure, I'm new to mock so I'm not an expert, however, I have just suffered the same problem and found that setting the side_effect
attribute to a function that returns an array fixes things
From your example code, change:
with patch("syncdatetime.py") as sync_mock: sync_mock.request.return_value = [obj, '']
to
with patch("syncdatetime.py") as sync_mock: sync_mock.request.side_effect = function_returning_list
and define
def function_returning_list(arg_list_of_choice): #anything you want to do goes here #then return your_list
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