I have an example of class mocking :
worker.py
import os
class Helper:
def __init__(self, path):
self.path = path
def get_folder(self):
base_path = os.getcwd()
return os.path.join(base_path, self.path)
def get_path(self):
return self.path
class Worker:
def __init__(self):
self.helper = Helper('db')
def work(self):
path = self.helper.get_path()
print(f'Working on {path}')
return path
And a test file : test_worker.py
from unittest import TestCase, mock
from worker import Worker, Helper
class TestWorkerModule(TestCase):
def test_patching_class(self):
with mock.patch('worker.Helper') as MockHelper:
MockHelper.return_value.get_path.return_value = 'testing'
worker = Worker()
self.assertEqual(worker.work(), 'testing')
The test returns ok as long as the 2 classes are in the same file. Separating them into 2 files worker_1.py for class Helper and worker_2.py for class Worker, the test fails with :
AssertionError: 'db' != 'testing'
Why ? And how can I correct this behaviour ?
Thanks
Lets say we have two files, worker.py and helper.py
worker.py:
from helper import Helper
class Worker:
def __init__(self):
self.helper = Helper('db')
def work(self):
path = self.helper.get_path()
print('Working on {path}')
return path
helper.py:
import os
class Helper:
def __init__(self, path):
self.path = path
def get_folder(self):
base_path = os.getcwd()
return os.path.join(base_path, self.path)
def get_path(self):
return self.path
What you did here is to import Helper class into worker module, so when you trying to do that at your test_worker.py:
from unittest import TestCase, mock
from worker import Worker
class TestWorkerModule(TestCase):
def test_patching_class(self):
with mock.patch('helper.Helper') as MockHelper:
MockHelper.return_value.get_path.return_value = 'testing'
worker = Worker()
self.assertEqual(worker.work(), 'testing')
result:
AssertionError: 'db' != 'testing'
- db
+ testing
you are patching the Helper class in helper.py module, but you already imported the Helper class into worker module, because of that you need to patch the Helper class in worker module, for example:
from unittest import TestCase, mock
from worker import Worker
class TestWorkerModule(TestCase):
def test_patching_class(self):
with mock.patch('worker.Helper') as MockHelper:
MockHelper.return_value.get_path.return_value = 'testing'
worker = Worker()
self.assertEqual(worker.work(), 'testing')
result:
Ran 1 test in 0.002s
OK
Another way to make it work for general use cases (lets say you want to patch Helper class in all modules that use it), it is to change worker.py to that:
import helper
class Worker:
def __init__(self):
self.helper = helper.Helper('db')
def work(self):
path = self.helper.get_path()
print('Working on {path}')
return path
here you are importing helper module, and use Helper class under helper module, so now your test.py should seem like that:
from unittest import TestCase, mock
from worker import Worker
class TestWorkerModule(TestCase):
def test_patching_class(self):
with mock.patch('helper.Helper') as MockHelper:
MockHelper.return_value.get_path.return_value = 'testing'
worker = Worker()
self.assertEqual(worker.work(), 'testing')
result:
Ran 1 test in 0.001s
OK
Thats worked because instead of importing the Helper class into worker module, we have imported the helper module, so patching "helper.Helper" will now really work correctly.