首页 > 解决方案 > 模拟 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()
    ...

在 test_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.call 返回 false。

关于如何模拟 other_module.funB 的任何线索?我在 StackOverflow 上发现了一个类似的问题,但没有得到解答,因此决定发布我的版本。

任何帮助将不胜感激,在此先感谢您。

标签: pythonunit-testingpytestpython-unittestpython-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/stackoverflow/67563601/demo.py               3      0   100%
src/stackoverflow/67563601/fun_list.py           6      0   100%
src/stackoverflow/67563601/other_module.py       4      1    75%   6
src/stackoverflow/67563601/test_demo.py         12      0   100%
--------------------------------------------------------------------------
TOTAL                                           25      1    96%

推荐阅读