Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Python mock patch not mocking the object

I am using the python mocking library and I am not sure why I get this result. Why only the second one got mocked and not the first one? What’s the best way to do it?

import unittest
from unittest.mock import patch, Mock

import requests
from requests import Session


def my_func():
    s = Session()
    print('my_func', type(s))


def my_func2():
    s = requests.Session()
    print('my_func2', type(s))


class Test(unittest.TestCase):

    @patch("requests.Session", new=Mock)
    def test1(self, *args):
        my_func()

    @patch("requests.Session", new=Mock)
    def test2(self, *args):
        my_func2()

Output

my_func <class 'requests.sessions.Session'>
my_func2 <class 'unittest.mock.Mock'>

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

This is a tricky nuance about Python namespaces. In the first one, my_func(), you used just Session (after importing it into your module namespace with from requests import Session). In my_func2() you used requests.Session.

@patch('requests.Session') is replacing Session in the requests module, so requests.Session will be the mock object. But it does not replace every reference to Session in every module–in fact that would be very difficult to do in Python.

Really, on a basic level, what patch() is doing is just setting requests.Session = Mock(). But to replace the reference to Session that’s already in your module’s global namespace it would have to set globals()['Session'] = Mock() as well.

In other words, you have to patch the object in the correct namespace.

If you have some module foo.py that contains:

from requests import Session

def my_func():
    s = Session()
    ...

then a separate test module test_foo.py in which you want to mock the Session class, you have to patch it in the namespace of foo, like:

import foo

@patch('foo.Session', ...)
def test_my_func():
    ...
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading