def simple_read_write():
with open("file", "r") as f:
data = json.load(f)
data["change"] = "some content"
with open("file", "w") as f:
json.dump(data, f)
How to mock this scenario, where the same file is opened in read mode and its contents read. Then after changing the content, the same file is opened up again in write mode to update the contents.
I have hit a road-block for mocking this scenario using mock_open
.
The function I implemented for the testing the above code is below. It gives me assertion error and I am not able to properly mock the read write scenarios of the same file.
class Example(unittest.TestCase):
@patch("builtins.open", new_callable=mock_open, read_data=json.dumps({"change":"old data"}))
@patch("builtins.open", new_callable=mock_open)
def TestSimpleReadWrite(self, write_mock, read_mock):
SampleFile.simple_read_write()
read_mock.assert_called_with("file", "r")
write_mock.assert_called_with("file", "w")
write_mock().write.assert_called_with(json.dumps({"change": "some content"}))
I finally found the solution to my above problem.
import unittest
from unittest.mock import patch, call
import check
class Example(unittest.TestCase):
@patch("json.load")
@patch("json.dump")
def test_simple_rtead_write(self, jdump_mock, jload_mock):
with patch("builtins.open") as open_mock:
jload_mock.return_value = {"change": "previous content", "prev": "yes"}
jdump_mock.side_effect = [True]
ret = check.simple_read_write()
self.assertEqual(ret["change"], "some content")
assert call("file", "r") in open_mock.call_args_list and \
call("file", "w") in open_mock.call_args_list
if __name__ == "__main__":
unittest.main()
I just had to mock the json.load
and json.dump
and use return_value
and side_effect
respectively.
Previously, I was making the mistake of adding two builtins.open
instead of one. Since the same builtins.open
mock will contain the call to both read
and write
, I just needed to use call
to check if read
and write
has been performed or not.