模拟 pytest 列表中存在的函数
Mock a function present inside a list in pytest
我想模拟列表中存在的函数并检查它是否至少被调用过一次。下面是我尝试过的类似实现:-
在fun_list.py中(funA和funB是other_module中的两个函数)
import other_module
FUN_LIST = [
other_module.funA,
other_module.funB,
]
def run_funs():
for fun in FUN_LIST:
fun()
在demo.py
from fun_list import run_funs
def run_demo():
...
run_funs()
...
测试中_demo.py
from demo import run_demo
@patch('other_module.funB')
def test_demo_funs(mocked_funB):
mocked_funB.return_value = {}
run_demo()
assert mocked_funB.called
在上述情况下,我试图在 other_module 中模拟 funB,但该函数没有被模拟,并且光标进入 other_module 中的实际 funB 内部。因此,断言 mocked_funB.called returns false.
关于如何模拟 other_module.funB 的任何线索?
我在 Whosebug 上找到了类似的 question,但没有人回答,所以决定 post 我的版本。
任何帮助将不胜感激,提前致谢。
您需要在导入被测模块之前进行模拟。导入模块时将执行模块范围内的代码。测试用例执行时通过装饰器mock已经来不及了。
例如
other_module.py
:
def funA():
pass
def funB():
pass
fun_list.py
:
import other_module
print('execute module scope code')
FUN_LIST = [
other_module.funA,
other_module.funB,
]
def run_funs():
for fun in FUN_LIST:
fun()
demo.py
:
from fun_list import run_funs
def run_demo():
run_funs()
test_demo.py
:
import unittest
from unittest.mock import patch
class TestDemo(unittest.TestCase):
@patch('other_module.funB')
def test_demo_funs(self, mocked_funB):
print('mock before import the module')
from demo import run_demo
mocked_funB.return_value = {}
run_demo()
assert mocked_funB.called
if __name__ == '__main__':
unittest.main()
测试结果:
mock before import the module
execute module scope code
.
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
Name Stmts Miss Cover Missing
--------------------------------------------------------------------------
src/Whosebug/67563601/demo.py 3 0 100%
src/Whosebug/67563601/fun_list.py 6 0 100%
src/Whosebug/67563601/other_module.py 4 1 75% 6
src/Whosebug/67563601/test_demo.py 12 0 100%
--------------------------------------------------------------------------
TOTAL 25 1 96%
我在 的带领下做了一些不同的修改。在我的例子中,我有多个这样的测试函数,它们模拟 funB 并调用 run_demo(最初是来自 Django.test 的 client.post() 调用)。如果较早的函数成功调用它,则其他后续补丁将失败(由于@slideshowp2 所述的相同原因)。所以,我改变了这个方法:-
在fun_list.py中(funA和funB是other_module中的两个函数)
import other_module
FUN_LIST = [
'funA',
'funB',
]
def run_funs():
for fun in FUN_LIST:
getattr(other_module, fun)()
在demo.py
from fun_list import run_funs
def run_demo():
...
run_funs()
...
测试中_demo.py
from demo import run_demo
@patch('other_module.funB')
def test_demo_funs(mocked_funB):
mocked_funB.return_value = {}
run_demo()
assert mocked_funB.called
我想模拟列表中存在的函数并检查它是否至少被调用过一次。下面是我尝试过的类似实现:-
在fun_list.py中(funA和funB是other_module中的两个函数)
import other_module
FUN_LIST = [
other_module.funA,
other_module.funB,
]
def run_funs():
for fun in FUN_LIST:
fun()
在demo.py
from fun_list import run_funs
def run_demo():
...
run_funs()
...
测试中_demo.py
from demo import run_demo
@patch('other_module.funB')
def test_demo_funs(mocked_funB):
mocked_funB.return_value = {}
run_demo()
assert mocked_funB.called
在上述情况下,我试图在 other_module 中模拟 funB,但该函数没有被模拟,并且光标进入 other_module 中的实际 funB 内部。因此,断言 mocked_funB.called returns false.
关于如何模拟 other_module.funB 的任何线索? 我在 Whosebug 上找到了类似的 question,但没有人回答,所以决定 post 我的版本。
任何帮助将不胜感激,提前致谢。
您需要在导入被测模块之前进行模拟。导入模块时将执行模块范围内的代码。测试用例执行时通过装饰器mock已经来不及了。
例如
other_module.py
:
def funA():
pass
def funB():
pass
fun_list.py
:
import other_module
print('execute module scope code')
FUN_LIST = [
other_module.funA,
other_module.funB,
]
def run_funs():
for fun in FUN_LIST:
fun()
demo.py
:
from fun_list import run_funs
def run_demo():
run_funs()
test_demo.py
:
import unittest
from unittest.mock import patch
class TestDemo(unittest.TestCase):
@patch('other_module.funB')
def test_demo_funs(self, mocked_funB):
print('mock before import the module')
from demo import run_demo
mocked_funB.return_value = {}
run_demo()
assert mocked_funB.called
if __name__ == '__main__':
unittest.main()
测试结果:
mock before import the module
execute module scope code
.
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
Name Stmts Miss Cover Missing
--------------------------------------------------------------------------
src/Whosebug/67563601/demo.py 3 0 100%
src/Whosebug/67563601/fun_list.py 6 0 100%
src/Whosebug/67563601/other_module.py 4 1 75% 6
src/Whosebug/67563601/test_demo.py 12 0 100%
--------------------------------------------------------------------------
TOTAL 25 1 96%
我在
在fun_list.py中(funA和funB是other_module中的两个函数)
import other_module
FUN_LIST = [
'funA',
'funB',
]
def run_funs():
for fun in FUN_LIST:
getattr(other_module, fun)()
在demo.py
from fun_list import run_funs
def run_demo():
...
run_funs()
...
测试中_demo.py
from demo import run_demo
@patch('other_module.funB')
def test_demo_funs(mocked_funB):
mocked_funB.return_value = {}
run_demo()
assert mocked_funB.called