James Burke James Burke - 28 days ago 10
Python Question

Replacing an object with mocks

I'm not sure what I'm doing wrong. Perhaps I have the wrong end of the stick with mocking. But my assumption was that when you use mocks it basically does some magic and replaces objects in your original code.

sites.py

class Sites:
def __init__(self):
pass

def get_sites(self):
return ['washington', 'new york']


my_module.py

from mylib import sites

def get_messages():
# get Sites
sm = sites.Sites()
sites = sm.get_sites()
print('Sites:' , sites)

for site in sites:
print('Test: ' , site)


my_test.py

import my_module
import unittest
from unittest.mock import patch


class MyModuleTestCase(unittest.TestCase):

@patch('my_module.Sites')
def test_process_the_queue(self, mock_sites):
mock_sites.get_sites.return_value = ['london', 'york']

print(mock_sites.get_sites())
my_module.get_messages()

if __name__ == '__main__':
unittest.main()


Running this I get the following output:

.['london', 'york']
Sites: <MagicMock name='Sites().get_sites()' id='139788231189504'>

----------------------------------------------------------------------
Ran 1 test in 0.002s

OK
[Finished in 0.1s]


I was expecting the second print output (which occurs within my_module.py) to be the same as the first and to loop through the list I passed through as a return value.

Any help would be greatly appreciated.

Updated
To show how I was originally importing my class

Answer

Python mock, while silly powerful, is definitely not very intuitive to use.

The print statement shows that you are patching my_module.Sites correctly but you have not registered the get_sites return value correctly, and it should be:

mock_sites.return_value.get_sites.return_value = ['london', 'york']

The print statement shows that there was a call to Sites().get_sites() registered on your patched object:

Sites: <MagicMock name='Sites().get_sites()' id='139788231189504'>

When reading this I find it helpful to translate () to return_value

Sites.return_value.get_sites.return_value

The return value you are missing represents the instantiation of the mock sites object: Sites().