模拟pytest中列表中的函数

2024-09-28 22:00:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我想模拟列表中的函数,并检查它是否至少被调用过一次。下面是我尝试过的类似实现:-

在fun\u list.py中(funA和funB是其他模块中的两个函数)

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\u 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

在上面的例子中,我试图模拟其他_模块中的funB,但函数没有被模拟,光标进入了其他_模块中的实际funB。因此,assert mocked_funB.called返回false

有关于我如何模仿其他模块的线索吗? 我在StackOverflow上发现了一个类似的question,但没有得到回答,所以决定发布我的版本

如有任何帮助,我们将不胜感激,并提前向您表示感谢


Tags: 模块函数runpyimportdemodeflist
2条回答

您需要在导入测试中的模块之前进行模拟。导入模块时将执行模块作用域中的代码。在执行测试用例时,通过decorator进行模拟已经太迟了

例如

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%

我从@slideshowp2's answer开始,对事情做了一些不同的修改。在我的例子中,我有多个这样的测试函数,它们模拟funB并调用run_demo(最初是来自Django.test的client.post()调用)。如果先前的函数调用成功,则其他后续修补程序将失败(原因与@slideshowp2所述相同)。所以,我改变了这个方法:-

在fun\u list.py中(funA和funB是其他模块中的两个函数)

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()
    ...

在test\u 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

相关问题 更多 >