Получение фактического возвращаемого значения для смоделированного file.read () - PullRequest
6 голосов
/ 05 января 2012

Я использую python-mock , чтобы смоделировать вызов открытия файла.Я хотел бы иметь возможность передавать поддельные данные таким образом, чтобы я мог проверить, что read() вызывается, а также использовать тестовые данные, не затрагивая файловую систему на тестах.

Вот что у меня естьдо сих пор:

file_mock = MagicMock(spec=file)
file_mock.read.return_value = 'test'

with patch('__builtin__.open', create=True) as mock_open:
    mock_open.return_value = file_mock

    with open('x') as f:
        print f.read()

Вывод этого - <mock.Mock object at 0x8f4aaec> intead 'test', как я предположил бы.Что я делаю не так при создании этого макета?

Редактировать:

Выглядит так:

with open('x') as f:
     f.read()

и это:

f = open('x')
f.read()

являютсяразные предметы.Использование mock в качестве менеджера контекста заставляет его возвращать новый Mock, тогда как вызов его напрямую возвращает все, что я определил в mock_open.return_value.Есть идеи?

Ответы [ 3 ]

11 голосов
/ 05 января 2012

Это звучит как хороший пример использования для объекта StringIO, который уже реализует интерфейс файла.Может быть, вы можете сделать file_mock = MagicMock(spec=file, wraps=StringIO('test')).Или вы могли бы просто заставить вашу функцию принимать объект, подобный файлу, и передавать ему StringIO вместо реального файла, избегая необходимости уродливого исправления обезьян.

Вы смотрели фиктивную документацию?*

http://www.voidspace.org.uk/python/mock/compare.html#mocking-the-builtin-open-used-as-a-context-manager

10 голосов
/ 08 апреля 2016

В Python 3 шаблон выглядит просто:

>>> import unittest.mock as um
>>> with um.patch('builtins.open', um.mock_open(read_data='test')):
...     with open('/dev/null') as f:
...         print(f.read())
...
test
>>>

(Да, вы можете даже издать / dev / null, чтобы вернуть содержимое файла)

1 голос
/ 07 июля 2018

на основе ответа @ tbc0 для поддержки Python 2 и 3 (многоверсионные тесты полезны для портов 2–3):

import sys
module_ = "builtins"
module_ = module_ if module_ in sys.modules else '__builtin__'

try:
    import unittest.mock as mock
except (ImportError,) as e:
    import mock 

with mock.patch('%s.open' % module_, mock.mock_open(read_data='test')):
    with open('/dev/null') as f:
        print(f.read())
...