【问题标题】:How can I mock a function called from a dictionary?如何模拟从字典中调用的函数?
【发布时间】:2019-11-02 13:41:08
【问题描述】:

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 是否被调用?

【问题讨论】:

  • 如果我不确定它是否会出现在字典上怎么办?

标签: python django unit-testing pytest python-unittest


【解决方案1】:

所以我认为这是两个独立的单元测试,一个用于函数 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}

【讨论】:

  • 我对@9​​87654323@ 有单独的测试,我只是想表明在我对a 的测试中调用了b
  • 不是对 b 的单独测试,而是对 _actions 的单独测试,您依赖的对象路由到您尝试调用的特定函数
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多