25

I'm trying to mock file open, and all of the examples show that I need to

@patch('open', create=True) 

but I keep getting

Need a valid target to patch. You supplied: 'open'

I know patch needs the full dotted path of open, but I have no idea what it is. As a matter of fact, I'm not even sure that's the problem.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
TzurEl
  • 792
  • 3
  • 9
  • 15
  • 2
    1. From what you've posted, we cannot tell you what the path should be, or if that's the problem. Give a [mcve]. 2. You know there's [`mock_open`](https://docs.python.org/3/library/unittest.mock.html#mock-open) specifically for this? – jonrsharpe Jul 19 '16 at 09:18

2 Answers2

32

You need to include a module name; if you are testing in a script, the name of the module is __main__:

@patch('__main__.open')

otherwise use the name of the module that contains the code you are testing:

@patch('module_under_test.open')

so that any code that uses the open() built-in will find the patched global instead.

Note that the mock module comes with a mock_open() utility that'll let you build a suitable open() call with file data:

@patch('__main__.open', mock_open(read_data='foo\nbar\nbaz\n'))
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • A question further: Could such a mock (with specified return_value) be used as a context manager (within a `with` statement)? – 0xc0de Jan 18 '17 at 08:12
  • @0xc0de: yes, the documenation I link to includes examples of `open()` being used with a `with` statement and being patched with `mock_open()`. – Martijn Pieters Jan 18 '17 at 16:22
  • Yes, I saw it later, after asking here. Thanks. – 0xc0de Jan 19 '17 at 06:24
  • A further question: how can you patch if two different files will be opened, and you want to provide `read_data` content for both? – Roelant Nov 08 '22 at 14:28
  • 1
    @Roelant: patch both. `patch()` can take a mock object to replace the target with, so create the mock first, then use `patch()` to replace two targets with the same object. Or, just create two mocks, as that might have benefits too (you can configure the mocks differently). – Martijn Pieters Nov 25 '22 at 13:15
32

In Python 3 you should use the decorator

@mock.patch("builtins.open", create=True)

or as context manager

with mock.patch('builtins.open', mock.mock_open(read_data=some_data)) as m:
    ...
Roelant
  • 4,508
  • 1
  • 32
  • 62
wierzbiks
  • 1,148
  • 10
  • 10