Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return Iterable With Mock Python

Tags:

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?

like image 325
Matt Avatar asked Jun 15 '11 19:06

Matt


People also ask

How do you mock iterable object?

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.

What is Side_effect in mock python?

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.

What is MagicMock Python?

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.

What is the difference between mock and MagicMock?

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.


2 Answers

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' 
like image 175
Brian Parry Avatar answered Sep 28 '22 00:09

Brian Parry


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 
like image 32
Dominic Barraclough Avatar answered Sep 28 '22 00:09

Dominic Barraclough