Python: Издевается над менеджером контекста
Я не понимаю, почему я не могу издеваться над NamedTemporaryFile.name в этом примере:
from mock import Mock, patch
import unittest
import tempfile
def myfunc():
with tempfile.NamedTemporaryFile() as mytmp:
return mytmp.name
class TestMock(unittest.TestCase):
@patch('tempfile.NamedTemporaryFile')
def test_cm(self, mock_tmp):
mytmpname = 'abcde'
mock_tmp.__enter__.return_value.name = mytmpname
self.assertEqual(myfunc(), mytmpname)
Результаты тестов:
AssertionError: <MagicMock name='NamedTemporaryFile().__enter__().name' id='140275675011280'> != 'abcde'
Ответы
Ответ 1
Вы устанавливаете неправильный макет: mock_tmp
не является менеджером контекста, но вместо этого возвращает менеджер контекста. Замените линию настройки следующим образом:
mock_tmp.return_value.__enter__.return_value.name = mytmpname
и ваш тест будет работать.
Ответ 2
Вот альтернативный вариант с pytest и mocker fixa, что также является обычной практикой:
def test_myfunc(mocker):
mock_tempfile = mocker.MagicMock(name='tempfile')
mocker.patch(__name__ + '.tempfile', new=mock_tempfile)
mytmpname = 'abcde'
mock_tempfile.NamedTemporaryFile.return_value.__enter__.return_value.name = mytmpname
assert myfunc() == mytmpname
Ответ 3
Расширяя ответ петра К, используя pytest и крепление насмешника.
def myfunc():
with tempfile.NamedTemporaryFile(prefix='fileprefix') as fh:
return fh.name
def test_myfunc(mocker):
mocker.patch('tempfile.NamedTemporaryFile').return_value.__enter__.return_value.name = 'tempfilename'
assert myfunc() == 'tempfilename'