[英]How to mock a function called in a function inside a module with the same name?
我正在嘗試使用unittest.mock
,但是出現錯誤:
AttributeError:沒有屬性“ get_pledge_frequency”
我具有以下文件結構:
pledges/views/
├── __init__.py
├── util.py
└── user_profile.py
pledges/tests/unit/profile
├── __init__.py
└── test_user.py
內部pledges/views/__init___.py
我有:
from .views import *
from .account import account
from .splash import splash
from .preferences import preferences
from .user_profile import user_profile
在內部, user_profile.py
我有一個名為user_profile
的函數,該函數在util.py
內部調用了一個名為get_pledge_frequency
的函數,如下所示:
def user_profile(request, user_id):
# some logic
# !!!!!!!!!!!!!!!!
a, b = get_pledge_frequency(parameter) # this is the function I want to mock
# more logic
return some_value
我在test_user.py
內部進行了如下測試:
def test_name():
with mock.patch(
"pledges.views.user_profile.get_pledge_frequency"
) as get_pledge_frequency:
get_pledge_frequency.return_value = ([], [])
response = c.get(
reverse("pledges:user_profile", kwargs={"user_id": user.id})
) # this calls the function user_profile inside pledges.user_profile
# some asserts to verify functionality
我已經檢查了其他問題,但是當有一個稱為模塊的函數被導入到__init__
文件中時,答案沒有涵蓋。
那么,有什么辦法可以解決這個問題? 我基本上已經將文件user_profile.py
重命名為profile
,然后將測試更改為引用此模塊中的函數,但是我想知道是否可以使函數和模塊保持相同的名稱。
事實證明,可以在同名模塊中模擬在函數內部調用的函數。 圍繞unittest.mock.patch()
小包裝可以使這種情況發生:
from unittest import mock
import importlib
def module_patch(*args):
target = args[0]
components = target.split('.')
for i in range(len(components), 0, -1):
try:
# attempt to import the module
imported = importlib.import_module('.'.join(components[:i]))
# module was imported, let's use it in the patch
patch = mock.patch(*args)
patch.getter = lambda: imported
patch.attribute = '.'.join(components[i:])
return patch
except Exception as exc:
pass
# did not find a module, just return the default mock
return mock.patch(*args)
代替:
mock.patch("module.a.b")
你需要:
module_patch("module.a.b")
基本思想是嘗試從可能的最長模塊路徑到最短路徑開始的模塊導入,如果導入成功,則將該模塊用作修補對象。
import module
print('module.a(): ', module.a())
print('module.b(): ', module.b())
print('--')
with module_patch("module.a.b") as module_a_b:
module_a_b.return_value = 'new_b'
print('module.a(): ', module.a())
print('module.b(): ', module.b())
try:
mock.patch("module.a.b").__enter__()
assert False, "Attribute error was not raised, test case is broken"
except AttributeError:
pass
module
測試文件 # __init__.py
from .a import a
from .a import b
# a.py
def a():
return b()
def b():
return 'b'
module.a(): b
module.b(): b
--
module.a(): new_b
module.b(): b
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.