[英]How to mock the import of a module in python?
考慮以下項目結構:
/project
- folder/
- some_config_module.py
- func.py
- test/
- __init__.py
- test_config.py
- test.py
假設以下代碼
# func.py
import folder.some_config_module as config
def search_for_data():
var = config.predefined_parameter
# rest of code
我現在想為search_for_data
編寫一個單元測試。 為了以明智的方式做到這一點,我需要模擬some_config_module
的導入,即我的嘗試
# test.py
import unittest
from unittest.mock import patch
import tests.test_config as test_config
from folder.func import serach_for_data
class TestSearchForData(unittest.TestCase):
@patch('folder.some_config_module')
def test_one(self, test_config):
self.assertEqual(search_for_data(), 0)
if __name__ == "__main__":
unittest.main()
這不會導致預期的行為:我想要的是test_one
內的search_for_data
導入test.test_config
而不是folder.some_config_module
。 這段代碼基於這個答案......但我似乎誤解了關於mock
的一些相當基本的東西......
由於您的 function search_for_data
使用在func
的全局命名空間中導入的名稱config
,因此您需要覆蓋它而不是覆蓋的folder.some_config_module
。
@patch('folder.func.config')
像import folder.some_config_module as config
這樣的導入等效於執行以下操作:
import folder.some_config_module
config = folder.some_config_module
del folder.some_config_module
因此,它將變量config
添加到該模塊( func.py
)的命名空間中,這就是search_for_data
正在使用的內容。 從search_for_data
的角度來看, config
是一個引用模塊的名稱還是引用其他東西都沒有關系,它只知道它需要從全局命名空間加載該名稱(在這種情況下它是模塊func.py
)
在運行時search_for_data
將在其全局命名空間( search_for_data.__globals__
)中查找config
,模擬修補此全局字典並將此字典中的名稱config
臨時替換為模擬 object 並在拆卸期間將其恢復。
import os.path as path
from unittest.mock import patch
def func():
print(path)
print(f"Before patch: {func.__globals__['path']}")
with patch("__main__.path"):
print(f"During patch: {func.__globals__['path']}")
func()
print(f"After patch: {func.__globals__['path']}")
輸出:
Before patch: <module 'posixpath' from '/usr/lib/python3.8/posixpath.py'>
During patch: <MagicMock name='path' id='140233829017776'>
<MagicMock name='path' id='140233829017776'>
After patch: <module 'posixpath' from '/usr/lib/python3.8/posixpath.py'>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.