Rather than monkeypatching open
in __builtins__
, you can patch it out in bmodule itself. The benefit of that is that only functions in bmodule will get your patched-out open function.
You can see more detail on this in the mock documentation.
So you can put your version of open in place by using patch.object
as a context manager:
from mock import patch
class TestCases(unittest.TestCase):
def test_something(self):
from amodule import bmodule
open_mock = mock.MagicMock(spec=open)
read_mock = mock.MagicMock()
open_mock.return_value.__enter__.return_value = read_mock
with patch.object(bmodule, 'open', open_mock, create=True):
self.assertTrue(bmodule.some_function())
self.assertEqual(open_mock.call_args_list, ['filename1', 'filename2'])
The with statement guarantees that the patch will be removed when execution leaves the with block. The create=True
part is needed to convince patch that you do intend to create the open
binding in the bmodule
namespace - this is a safety precaution to prevent people from accidentally mocking the wrong name, but in your case it's needed because open lives in __builtins__
but you want to bind it in bmodule
.