Python 3.x 在Python中模拟全局/模块级变量

Python 3.x 在Python中模拟全局/模块级变量,python-3.x,mocking,python-unittest,Python 3.x,Mocking,Python Unittest,我有一个模块,如下所示: import psycopg2 client = vault_client(vault_url, vault_certs_path, credentials) vault_data = client.read(vault_path)['data'] def do_thing connection = psycopg2.connect( dbname=vault_data['database'],

我有一个模块,如下所示:

import psycopg2

client = vault_client(vault_url, vault_certs_path, credentials)
vault_data = client.read(vault_path)['data']


def do_thing
     connection = psycopg2.connect(
                dbname=vault_data['database'],
                host=vault_data['cluster_name'],
               ...
               )
我如何测试这个do_thing方法。我需要模拟vault_数据和psycopy2的导入。我需要确保:

  • psycopg2.connect方法接收正确的参数
  • 如何模拟
    vault\u client
    方法以返回模拟,然后在模拟上调用
    read
    方法时返回字典
  • 我有这个,但真正的方法会被调用:

        @mock.patch("sources.segment.handler")
        @mock.patch("sources.segment.handler.psycopg2")
        def test_attempts_to_connect_to_redshift(self, mock_psycopg2, mock_handler):
            mock_handler.vault_client.return_value = {
                "data": {
                    "database": "some_database",
                    "cluster_name": "some_cluster_name",
                    "port": "some_port",
                    "username": "some_username",
                    "password": "some_password",
                }
            }
            do_thing()
    
            mock_psycopg2.connect.assert_called_with("some database")
            ...
    

    这里的问题似乎是,在导入带有
    do\u thing()
    的模块之前,模仿某些东西已经太迟了。您可以尝试以下技巧:

    import sys
    from unittest.mock import MagicMock
    
    psycopg2_mock = MagicMock()
    sys.modules['psycopg2'] = psycopg2_mock
    import module_with_do_thing
    del sys.modules['psycopg2']
    
    class TestSomething(unittest.TestCase):
        ...
        def test_attempts_to_connect_to_redshift(self):
            ...
            assert psycopg2_mock.has_required_properties
    

    将带有_do _thing的导入模块_移动到带有正确补丁的实际测试方法也可能会起作用。

    vault客户端部件呢?该部分还在导入时进行真正的api调用。如何停止?同样,只需在
    sys.modules
    中覆盖另一个模块。这里发生了什么?是否将psycopg2设置为模拟,导入模块,然后删除我们设置的模拟?