The top answer is useful but I expanded on it a bit.
If you want to set the value of your file object (the f
in as f
) based on the arguments passed to open()
here's one way to do it:
def save_arg_return_data(*args, **kwargs):
mm = MagicMock(spec=file)
mm.__enter__.return_value = do_something_with_data(*args, **kwargs)
return mm
m = MagicMock()
m.side_effect = save_arg_return_array_of_data
# if your open() call is in the file mymodule.animals
# use mymodule.animals as name_of_called_file
open_name = '%s.open' % name_of_called_file
with patch(open_name, m, create=True):
#do testing here
Basically, open()
will return an object and with
will call __enter__()
on that object.
To mock properly, we must mock open()
to return a mock object. That mock object should then mock the __enter__()
call on it (MagicMock
will do this for us) to return the mock data/file object we want (hence mm.__enter__.return_value
). Doing this with 2 mocks the way above allows us to capture the arguments passed to open()
and pass them to our do_something_with_data
method.
I passed an entire mock file as a string to open()
and my do_something_with_data
looked like this:
def do_something_with_data(*args, **kwargs):
return args[0].split("\n")
This transforms the string into a list so you can do the following as you would with a normal file:
for line in file:
#do action