Python 单元测试:模拟从 class 对象调用的外部库函数

Python unittest: Mock an external library function called from a class object

您好,我有以下代码;

我正在尝试测试里面的加载函数file_a;下载是我导入的外部模块中的功能

file_a.py

from foo import download

class Bar()
    __init__(self, arg_1):
        self.var = arg_1

    def load(self):
        if self.var == "latest_lib":
            download("latest_lib")

我写的测试像

test.py

@patch(file_a.download)
def test_download():
    import file_a
    bar = file_a.Bar("latest_lib")
    bar.load()
    file_a.download.assert_called() 

但似乎 bar 对象调用的不是模拟下载,而是导入的下载。我怎样才能解决这个问题并使我的测试通过?

我认为您缺少模拟设置:

@patch("foo.download")
def test_download(mock_download):
    from file_a import Bar

    Bar("latest_lib").load()
    mock_download.assert_called()

我试过用你自己的代码看看哪里错了。有一些语法错误并不重要,但主要问题是您应该将字符串传递给 patch 以使其工作。

这是我对您的代码所做的修改,使这一切成为现实:

# file_a.py

from pprint import pprint as pp

class Bar():
    def __init__(self, arg_1):
        self.var = arg_1

    def load(self):
        if self.var == "latest_lib":
            pp("latest_lib")

并且:

# test_file_a.py

import unittest
from unittest.mock import patch


class TestStringMethods(unittest.TestCase):
    @patch("file_a.pp")
    def test_download(self, pp):
        import file_a
        bar = file_a.Bar("latest_lib")
        bar.load()
        pp.assert_called()


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

备注:

  1. 您需要将字符串传递给 patch 以使其在运行时模拟对象。
  2. 您必须在测试函数中接收模拟对象。
  3. 我在这里使用了基于 class 的测试,因为我想使用 unittest 标准库,但如果您使用 [=15],则不必这样做=].

还有来自 official doc 的最后一个注释:

The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.