I have tested your code in my system and as @Gameplay says the only problem is the path of the module that you use in the patch()
instruction.
The most important modification
I have changed:
# YOUR
with patch('update_baseline_manifest.read_file', return_value=test_contents) as mock_read, \
patch('update_baseline_manifest.write_file') as mock_write:
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++
# TO MINE: I have added in the patch() instruction the
# path to reach the file update_baseline_manifest.py
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++
with patch('a.b.update_baseline_manifest.read_file', return_value=test_contents) as mock_read, \
patch('a.b.update_baseline_manifest.write_file') as mock_write:
In fact you patch the objects point by the names update_baseline_manifest.read_file
and update_baseline_manifest.write_file
but when your test code invokes the function update_baseline_manifest
(code under test), this function calls the real objects and not the mocked objects.
The rest of the answer details the code used to replicate the test in my system.
Your production code in my system
I have recreated your script update_baseline_manifest.py
as followed:
def update_baseline_manifest(baseline_manifest_path, vbf_info_map, logger):
""" Updates manifest as per the part numbers in the vbfs_map """
try:
manifest_contents = read_file(baseline_manifest_path)
# Do something
write_file(manifest_contents, baseline_manifest_path)
return 0
except Exception as ex:
print(str(ex))
def read_file(file_path):
print('called read')
with open(file_path, 'r') as file:
return yaml.safe_load(file)
def write_file(contents, file_path):
print('called write')
with open(file_path, 'w') as file:
yaml.dump(contents, file)
I have added only some instructions in the function update_baseline_manifest
:
return 0
to pass your test self.assertEqual(result, 0)
except Exception as ex:
to complete your try:
instruction
The file is saved in the path a/b/update_baseline_manifest.py
where a
and b
contains the file __init__.py
Your test code in my system
My test code is the following:
import unittest
from unittest.mock import patch
from a.b.update_baseline_manifest import update_baseline_manifest
# utility class for not change your test code
class ARGS:
baseline_manifest_path = "/path/to/manifest"
vbf_info_map = "vbf info map"
logger = "logger"
class MyTestCase(unittest.TestCase):
args = ARGS()
def test_update_baseline_manifest(self):
test_contents = 'sample contents'
with patch('a.b.update_baseline_manifest.read_file', return_value=test_contents) as mock_read \
patch('a.b.update_baseline_manifest.write_file') as mock_write:
result = update_baseline_manifest(self.args.baseline_manifest_path,
self.args.vbf_info_map,
self.args.logger)
mock_read.assert_called_with(self.args.baseline_manifest_path)
#mock_write.assert_called_with(contents_written, self.args.baseline_manifest_path)
mock_write.assert_called_with(test_contents, self.args.baseline_manifest_path)
self.assertEqual(result, 0)
if __name__ == '__main__':
unittest.main()
In the test file I have added the following import
:
import unittest
from unittest.mock import patch
I have also added the (utility) class ARGS
to define the attribute arg
of MyTestCase
:
class ARGS:
baseline_manifest_path = "/path/to/manifest"
vbf_info_map = "vbf info map"
logger = "logger"
I have modified one your test as followed:
# your test
#mock_write.assert_called_with(contents_written, self.args.baseline_manifest_path)
# my test
mock_write.assert_called_with(test_contents, self.args.baseline_manifest_path)
The last, but the most important modification (as I have written at the top of the answer):
I have changed the path inside the patch
instructions.
The output
The output of the execution is:
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
In the output is not present any printed message so we are sure that the production code is not invoked!
This link is very useful to understand where to patch.
Other useful examples are in the following posts: