#python #unit-testing #mocking
#python #модульное тестирование #издевательство
Вопрос:
прежде всего, извините, если на этот вопрос был дан ответ ранее, но я искал повсюду и ничего не мог найти.
У меня есть функция, которая делает это (вкратце):
def func(path):
with open(path) as f:
json.load(f)
Я хочу провести модульное тестирование, и мне бы хотелось, чтобы при использовании open в качестве context manager, f
это имя аргумента, который я передал в open. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу имитировать метод enter в соответствующем модуле, он каждый раз ломается. Это то, что я делаю до сих пор:
def setUp(self):
# Setup the content of the config files for the tests
json.load = MagicMock(side_effect=file_content)
# Opening a file returns the name of the file
builtins.open = MagicMock(side_effect=lambda x: x) #1
builtins.open.__enter__ = MagicMock(side_effect=builtins.open.return_value) #2
MagicMock номер 1 делает то, что я ожидаю от него, когда я запускаю open («test»), он возвращает «test». Тем не менее, я не могу имитировать ввод, чтобы вернуть все, что я передал в open, это всегда завершается неудачей с AttributeError: __enter__
. Я пытался также делать
builtins.open.return_value.__enter__ = MagicMock...
безуспешно. Кто-нибудь может подумать о том, как этого можно достичь? Я видел, как издеваться над магическими методами, и я подумал, что меня устраивает unittest mocking, но в этом случае я не могу найти подходящее решение. Спасибо!
Комментарии:
1. в этой ситуации
__enter__
должен возвращаться сам, поэтому он должен возвращатьbuiltins.open
который вы определяете в строке выше. если вы хотите установить возвращаемое значение, то сделайте это для этой переменной
Ответ №1:
Я понял!
Мне пришлось определить side_effect динамически, но, похоже, работает нормально. Это то, что я сделал:
def setUp(self):
# Setup the content of the config files for the tests
json.load = MagicMock(side_effect=file_content)
# Opening a file returns the name of the file
def get_mock_context(filename):
mock_context = MagicMock()
mock_context.__enter__.return_value = filename
mock_context.__exit__.return_value = False
return mock_context
builtins.open = MagicMock(side_effect=get_mock_context)
Таким образом, возвращаемое значение является макетом, в котором методы __enter__
и __exit__
возвращают именно то имя файла, которое я передал при вызове open.