使用 unittest 和 mock 在 python 函数中修补变量

Patching variable in a python function with unittest and mock

我有以下 my_func.py 和 create_config 功能。

*my_func.py

from fabric.state import env

def create_config(node_name):
    config = {
    "log_level": "INFO",
    "addr1": "127.0.0.1",
    }
    config["addr2"] = env.host
    return config

我尝试了以下方法来模拟 env.host 变量,其中 env 是从 fabric.state.

导入的

*test.py

import unittest
import my_func
import mock


class MyTestCase(unittest.TestCase):
    def setUp(self):
        self.master_config = {
              "log_level": "INFO",
              "addr2": "0.0.0.0",
              "addr1": "127.0.0.1",
        }

    @mock.patch('env.host')
    def test_create_consul_config(self, mock_host):
        mock_host.return_value = "0.0.0.0"
        result = my_func.create_config('master')
        self.assertDictEqual(self.master_config, result)


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

我在 'env' 中遇到导入错误。使用 python mock.

在函数中模拟变量的最佳方法是什么
ImportError: No module named env

mock variable env.host?

先获取env的类型

In [6]: from fabric.state import env

In [7]: type(env)
Out[7]: fabric.utils._AttributeDict

env.host是一个class的实例变量,mock有点不同,mock_env是object(AttributeDict),instance_variablehost的赋值是直接的赋值,不带 return_value

@mock.patch('my_func.env')
def test_create_consul_config(self, mock_env):
    mock_env.host = 'xxx'
    result = my_func.create_config('master')

    self.assertDictEqual(self.master_config, result)

来自unittest.mock documentation on patch(注意targetpatch的第一个参数):

target should be a string in the form 'package.module.ClassName'. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are calling patch() from. The target is imported when the decorated function is executed, not at decoration time.

因此您需要包含要修补的函数的完整路径。另请注意,在 where to patch 中,目标应该是使用 function/object 的路径,而不是定义它的路径。

因此将您的 patch 调用更改为:

@mock.patch("my_func.env.host")

应该修复 ImportError