Python: Mocking a context manager
You are setting the wrong mock: mock_tmp
is not the context manager, but instead returns a context manager. Replace your setup line with:
mock_tmp.return_value.__enter__.return_value.name = mytmpname
and your test will work.
To expand on Nathaniel's answer, this code block
with tempfile.NamedTemporaryFile() as mytmp:
return mytmp.name
effectively does three things
# Firstly, it calls NamedTemporaryFile, to create a new instance of the class.
context_manager = tempfile.NamedTemporaryFile()
# Secondly, it calls __enter__ on the context manager instance.
mytmp = context_manager.__enter__()
# Thirdly, we are now "inside" the context and can do some work.
return mytmp.name
When you replace tempfile.NamedTemporaryFile
with an instance of Mock
or MagicMock
context_manager = mock_tmp()
# This first line, above, will call mock_tmp().
# Therefore we need to set the return_value with
# mock_tmp.return_value
mytmp = context_manager.__enter__()
# This will call mock_tmp.return_value.__enter__() so we need to set
# mock_tmp.return_value.__enter__.return_value
return mytmp.name
# This will access mock_tmp.return_value.__enter__.return_value.name