如何模拟从字典调用的函数?

How can I mock a function called from a dictionary?

test.py:

@pytest.mark.django_db
def test_b_called(mocker):
    b = mocker.patch('app.service.b')

    service.a('b')
    assert b.called

service.py:

def a(type):
    _actions[type]()

def b():
    pass

_actions = { 'b': b }

我的测试将失败,因为我的补丁没有像我预期的那样工作。我在这里做错了什么?如果 a 直接调用 b 而不是使用该词典,这绝对有效。我已经对此进行了测试。我知道你可以用 patch.dict 模拟字典,但我如何测试 b 被调用了?

所以我认为这是两个独立的单元测试,一个用于函数 a,一个用于字典 _actions。

_actions 不仅仅是一个简单的字典,而是某种意义上的动态函数调用。因此,如果您真的只是测试函数 a,那么您需要修补 _actions 对象并只测试函数范围内的功能。

_actions 不在测试范围内,应像任何其他方法一样单独测试。

from unittest import TestCase
from unittest.mock import patch
from stack_overflow import a,b,c, _actions

class TestStack(TestCase):

    def setUp(self):
        super().setUp()

    def tearDown(self):
        super().tearDown()

    @patch.dict('stack_overflow._actions',{'b':b})
    def test_a(self):
        self.assertEqual(5,a('b'))

    def test__actions_def_b(self):
        self.assertEqual(_actions['b'],b)

    def test__actions_def_c(self):
        self.assertEqual(_actions['c'],c)
def a(type):
    current_actions = _actions
    return _actions[type]()

def b():
    return 5

def c():
    return 7

_actions = { 'b': b, 'c': c}

我试图用一个什么都不做的函数来模拟字典操作。相反,我应该将它模拟成一个 MagicMock 函数,这也是补丁的作用。

patch.dict(
    'app.service._actions',
    {'b': MagicMock} # MagicMock is imported from unittest.mock
)