I want to patch a class in a Python library and mock its methods independently in several tests. My approach works if I run the tests separately. However, if I run the tests using $ python -m unittest test_*.py
the second test appears to use the patched object from the first and fails.
Here's a simplified version of my setup. (In the real scenario I have a more complex dependency on the mocked class and multiple tests in each test class using different mock functions as side effect.)
Files:
lib.py
test_1.py
test_2.py
lib.py:
from requests_oauthlib import OAuth2Session
from oauthlib.oauth2 import BackendApplicationClient
client = BackendApplicationClient(client_id='a client')
session = OAuth2Session(client=client)
def get_data():
return session.get('https://some.url.com/data')
test_1.py:
import unittest
from unittest.mock import patch
with patch('requests_oauthlib.OAuth2Session') as MockSession:
mock_session = MockSession.return_value
from .lib import get_data
def mock_get(url):
return f'some data from {url}'
class Test(unittest.TestCase):
def test_get_data(self):
mock_session.get.side_effect = mock_get
self.assertEqual(get_data(), 'some data from https://some.url.com/data')
test_2.py:
import unittest
from unittest.mock import patch
with patch('requests_oauthlib.OAuth2Session') as MockSession:
mock_session = MockSession.return_value
from .lib import get_data
def mock_get(url):
return f'other data from {url}'
class Test(unittest.TestCase):
def test_get_data(self):
mock_session.get.side_effect = mock_get
self.assertEqual(get_data(), 'other data from https://some.url.com/data')
When doing
$ python -m unittest test_1.py
$ python -m unittest test_2.py
both tests yield OK
.
Doing
$ python -m unittest test_*.py
fails with
AssertionError: 'some data from https://some.url.com/data' != 'other data from https://some.url.com/data'
I also tried to use patch()
like so:
patcher = patch('requests_oauthlib.OAuth2Session')
MockSession = patcher.start()
mock_session = MockSession()
from .lib import get_data
and introduce explicit module teardown:
def tearDownModule():
patcher.stop()
but got the same results.
Finally, I tried moving the patch()
into a class setup:
import unittest
from unittest.mock import patch
my_get_data = None
def mock_get(url):
return f'some data from {url}'
class Test(unittest.TestCase):
patcher = None
mock_session = None
@classmethod
def setUpClass(cls):
global my_get_data
cls.patcher = patch('requests_oauthlib.OAuth2Session')
MockSession = cls.patcher.start()
cls.mock_session = MockSession()
from python3.test.operators.com.sap.mdi.consumer.v2.tmp_c.lib import get_data
my_get_data = get_data
@classmethod
def tearDownClass(cls):
cls.patcher.stop()
def test_get_data(self):
self.mock_session.get.side_effect = mock_get
self.assertEqual(my_get_data(), 'some data from https://some.url.com/data')
but still got the same AssertionError
.
What am I doing wrong?