简体   繁体   中英

Patching imported open from imported file with mock

I have two files:

#file1.py
def_writefile():
    ...
    fp = open('file')
    fp.write('blah')
    ...


#file2.py
file1.writefile()

I've tried patching open different ways:

#test_file.py
fn = mock.mock_open()
with mock.patch('__builtin__.open', fn):
    file1.writefile()

with mock.patch('file1.open', fn):
    file1.writefile()

with mock.patch('file2.open', fn):
    file1.writefile()

with mock.patch('__main__.open', fn, create=True):
    file1.writefile()

assert(mock_file().write.called_once_with('blah'))

But none of them seem to work. What is the correct way to patch a builtin like open from an imported module using mock?

You want this:

import file1

fn = mock.mock_open()
with mock.patch('file1.open', fn, create=True):
    file1.writefile()

fn().write.assert_called_once_with('blah')

You need to mock the open function that will be used in file1.py , so we pass 'file1.open' isntead of '__main__.open' . The other piece you were missing is that you weren't using the right function to make sure write was called with the correct parameters - you need to use the assert_called_once_with function that's built into the Mock class.

create=True is required because the open function won't be found in the file1 class at import time, because the open function won't actually be pulled into the module until runtime. Normally that means mock will thrown an exception saying file1 is missing the attribute. Adding create=True makes mock create the attribute when it doesn't find it, and is mentioned in the docs as being useful for this situation:

This is useful for writing tests against attributes that your production code creates at runtime

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM