如果从列表中调用,则不会模拟 python 函数 [英] python function not mocked if called from list

查看:45
本文介绍了如果从列表中调用,则不会模拟 python 函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当从函数列表中调用函数时,我试图模拟该函数.

以下有效:

# demo_module.py导入 demo_module_bdef run_me():run_me_too()

# demo_module_bdef run_me_too():经过

# test.py从 demo_module 导入 run_me从 demo_module_b 导入 run_me_too@patch('demo_module_b.run_me_too')def test_run_me_with_patch(mock_run_me_too):运行_我()断言 mock_run_me_too. called # PASSES

以下失败:

# demo_module.py导入 demo_module_b过程 = [demo_module_b.run_me_too,]def run_me():进程[0]()

# demo_module_bdef run_me_too():经过

# test.py从 demo_module 导入 run_me从 demo_module_b 导入 run_me_too@patch('demo_module_b.run_me_too')def test_run_me_with_patch(mock_run_me_too):运行_我()断言 mock_run_me_too. called # 失败

有没有办法在不需要模拟列表的情况下让它工作?

编辑 1

这也失败了(并且直接导入两个测试都失败了):

# demo_module.py从 demo_module_b 导入 run_me_too进程 = [run_me_too,]def run_me():processes[0]() # 测试失败run_me_too() # 在测试中也失败

解决方案

您需要在导入被测模块之前进行模拟.导入模块时将执行模块范围内的代码.测试用例执行时通过装饰器进行模拟已经太晚了.

例如

demo_module.py:

import demo_module_b过程 = [demo_module_b.run_me_too,]def run_me():进程[0]()

demo_module_b.py:

def run_me_too():经过

test_demo_module.py:

import unittest从 unittest.mock 导入补丁类 TestDemoModule(unittest.TestCase):@patch('demo_module_b.run_me_too')def test_run_me_with_patch(self, mock_run_me_too):从 demo_module 导入 run_me运行_我()断言 mock_run_me_too.call如果 __name__ == '__main__':单元测试.main()

测试结果:

<预><代码>.----------------------------------------------------------------------在 0.002 秒内运行 1 次测试好的Name Stmts Miss Cover Missing-------------------------------------------------------------------------------src/stackoverflow/61774393/demo_module.py 4 0 100%src/stackoverflow/61774393/demo_module_b.py 2 1 50% 2src/stackoverflow/61774393/test_demo_module.py 10 0 100%-------------------------------------------------------------------------------总计 16 1 94%

I am trying to mock a function when the function is called from a list of functions.

The below works:

# demo_module.py

import demo_module_b

def run_me():
    run_me_too()

# demo_module_b

def run_me_too():
    pass

# test.py

from demo_module import run_me
from demo_module_b import run_me_too

@patch('demo_module_b.run_me_too')
def test_run_me_with_patch(mock_run_me_too):
    run_me()
    assert mock_run_me_too.called # PASSES

The below fails:

# demo_module.py

import demo_module_b

PROCESS = [
    demo_module_b.run_me_too,
]

def run_me():
    PROCESSES[0]()

# demo_module_b

def run_me_too():
    pass

# test.py

from demo_module import run_me
from demo_module_b import run_me_too

@patch('demo_module_b.run_me_too')
def test_run_me_with_patch(mock_run_me_too):
    run_me()
    assert mock_run_me_too.called # FAILS

Is there a way to get this to work without needing to mock the list to?

Edit 1

This also fails (And importing directly fails both tests):

# demo_module.py

from demo_module_b import run_me_too

processes = [
    run_me_too,
]


def run_me():
    processes[0]() # FAILS IN TEST
    run_me_too() # ALSO FAILS IN TEST

解决方案

You need to mock before importing the module under test. The code in the module scope will be executed when import the module. It is too late to mock through the decorator when the test case is executed.

E.g.

demo_module.py:

import demo_module_b

PROCESSES = [
    demo_module_b.run_me_too,
]


def run_me():
    PROCESSES[0]()

demo_module_b.py:

def run_me_too():
    pass

test_demo_module.py:

import unittest
from unittest.mock import patch


class TestDemoModule(unittest.TestCase):
    @patch('demo_module_b.run_me_too')
    def test_run_me_with_patch(self, mock_run_me_too):
        from demo_module import run_me
        run_me()
        assert mock_run_me_too.called


if __name__ == '__main__':
    unittest.main()

test result:

.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK
Name                                             Stmts   Miss  Cover   Missing
------------------------------------------------------------------------------
src/stackoverflow/61774393/demo_module.py            4      0   100%
src/stackoverflow/61774393/demo_module_b.py          2      1    50%   2
src/stackoverflow/61774393/test_demo_module.py      10      0   100%
------------------------------------------------------------------------------
TOTAL                                               16      1    94%

这篇关于如果从列表中调用,则不会模拟 python 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆