未调用 python 模拟函数

sim*_*nes 3 python mocking python-unittest python-unittest.mock

我正在测试 python 代码(一个 django 3.0.5 项目,虽然我认为它不相关),但我无法调用我的模拟对象的函数。这是我的代码:

**myproject.mypackage.myhelpers**


def get_dict():
    return dict()

**myproject.mypackage.mythings**

from .myhelpers import get_dict


def use_dict():
    the_dict = get_dict()
    pass
    return


**myproject.tests.test_mythings**

from ..mypackage import mythings
import unittest
import unittest.mock as mock


class MyThingsTests(unittest.TestCase):

    @mock.patch('myproject.mypackage.myhelpers')
    def test_using_dict(self, mock_myhelpers):
        test_dict = {
            "hi": "foo",
            "there": "bar",
            "sir": "foobar"
        }

        mock_myhelpers.get_dict.return_value = test_dict

        mythings.use_dict()

        mock_myhelpers.get_dict.assert_called_once()
Run Code Online (Sandbox Code Playgroud)

但是最终测试失败并出现错误:

AssertionError: Expected 'get_dict' to have been called once. Called 0 times

Del*_*lan 5

试试这个:

@mock.patch('myproject.mypackage.mythings.get_dict')
def test_using_dict(self, mock_get_dict):
    test_dict = {
        "hi": "foo",
        "there": "bar",
        "sir": "foobar"
    }

    mock_get_dict.return_value = test_dict
Run Code Online (Sandbox Code Playgroud)

哪里补丁的文档的部分解释这一点。

根据我的理解,在你做补丁之前myproject.mypackage.mythings已经导入了“真实” get_dict。因此,如果您像 那样修补它@mock.patch('myproject.mypackage.myhelpers'),则只有myhelpers模块会“知道”它已被修补。该mythings模块仍将具有对 real 的引用get_dict

我认为我上面所做的修补方式的替代方法是更改​​导入get_dict方式。而不是get_dict直接导入,只需导入myhelpers并使用get_dictas myhelpers.get_dict。然后你应该能够保持你的修补方式相同,因为get_dict将从myhelpers具有修补方法的方法中查找。

  • 这就是答案。我想补充一点,在考虑修补时,必须考虑执行期间的导入,而不是它们的编写方式。当您修补“method_a”以测试“module_b”中包含“module_b”中的“import method_a from module_a”时,您需要的补丁是“@patch('module_b.method_a')”。 (3认同)
  • @thlik,我从文档中根本不清楚这一点。我想试着总结一下。对于该特定上下文,修补必须使用 **使用它的地方!** 的路径。**不是**从定义的地方来看。 (2认同)