I'm writing a unit test for a function that creates a folder using os.makedirs
and os.path.join
. When I'm trying to mock the specific os.path.join used in the class BuilddataHelpers it also patches the os.path.join
in the test file. How can I specifically patch the os.path.join
in the file that is being tested while still using os.path.join
in the test file?
datamanager/builddatahelpers.py
import os
PATH = 'not/test/data/either'
class BuilddataHelpers:
def create_folder(self, folder_name):
create_folder_path = os.path.join(PATH, folder_name)
os.makedirs(create_folder_path, exist_ok = True)
return path
datamanager/datamanager.py
class DataManager(BuilddataHelpers):
...
test_builddatahelpers.py
import os
class TestBuilddataHelpers(unittest.TestCase):
global TEST_PATH
TEST_PATH = 'tests/data'
def setUp(self):
super(TestBuilddataHelpers, self).setUp()
self.dm = DataManager()
@patch('datamanager.builddatahelpers.os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
folder_name = 'test_folder'
self.dm.create_folder(folder_name)
self.assertTrue(os.path.exists(os.path.join(TEST_PATH, folder_name)))
print('SUBFOLDER PATH: ' , os.path.join('not', 'test', 'data'))
outputs SUBFOLDER PATH: tests/data
. The folder is still created since os.makedirs
is not patched.
CodePudding user response:
In your tested code, you do import os
, which means that os.path.join
will be used instead of a local reference. So if you do:
@patch('datamanager.builddatahelpers.os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
...
this is exactly the same as writing:
@patch('os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
...
That first version only would make sense if you had used from x import y
in the tested code. In your case, os.path.join
will be patched for all modules using it.
If you want to use the original os.path.join
, you have to cache it somewhere.
One possibility is to just use:
from os.path import join
...
@patch('os.path.join', return_value=TEST_PATH)
def test_create_folder_structure_on_ftp(self, mock_os_join):
folder_name = 'test_folder'
self.dm.create_folder(folder_name)
self.assertTrue(os.path.exists(join(TEST_PATH, folder_name)))
print('SUBFOLDER PATH: ' , join('not', 'test', 'data'))
The local reference to os.path.join
saved in join
will not be patched. You could also cache it as a class variable:
import os
class TestBuilddataHelpers(unittest.TestCase):
TEST_PATH = 'tests/data'
join = os.path.join
...
self.assertTrue(os.path.exists(self.join(TEST_PATH, folder_name)))
which shall have the same effect.