【问题标题】:Can not monkeypatch imported module无法对导入的模块进行monkeypatch
【发布时间】:2020-06-15 07:22:18
【问题描述】:

我有一个用 Python 编写的非常简单的Google Cloud Function,它通过他们的 Python 库引用了 Google 的 Secret manager。

代码很简单,如下所示:

import os
from google.cloud import secretmanager
import logging

client = secretmanager.SecretManagerServiceClient()
secret_name = "my-secret"
project_id = os.environ.get('GCP_PROJECT')
resource_name = "projects/{}/secrets/{}/versions/latest".format(project_id, secret_name)
response = client.access_secret_version(resource_name)
secret_string = response.payload.data.decode('UTF-8')

def new_measures_handler(data, context):
    logging.info(secret_string)
    print('File: {}.'.format(data['name']))

然后我有一个简单的单元测试,它试图利用monkey patching

import main

def test_print(capsys, monkeypatch):
    # arrange
    monkeypatch.setenv("GCP_PROJECT", "TestingUser")
    monkeypatch.setattr(secretmanager, "SecretManagerServiceClient", lambda: 1)

    name = 'test'
    data = {'name': name}

    # act
    main.new_measures_handler(data, None)
    out, err = capsys.readouterr()

    #assert
    assert out == 'File: {}.\n'.format(name)

环境变量的模拟一切顺利,但我无法模拟secretmanager。它继续尝试调用实际的 API。我的最终目标是模拟 secretmanager.SecretManagerServiceClient() 并使其返回一个对象,以后可以使用该对象:client.access_secret_version(resource_name)(我认为我也需要模拟)

【问题讨论】:

  • 试试:monkeypatch.setattr(main.secretmanager, "SecretManagerServiceClient", lambda: 1)。必须这样做,因为您将 secretmanager 导入到 main 的命名空间中。
  • @jordanm 我试过了,但它继续失败并出现同样的错误。尝试调用实际的 API。
  • 啊,我明白了。这是因为您在顶级范围内调用 SecretManagerServiceClient()。这意味着该对象是在执行 import main 时创建的,即在您的猴子补丁之前。使用if __name__ == '__main__'
  • @jordanm 那么,您的建议是在函数声明上方添加if __name__ == '__main__',并将对象初始化(client = secretmanager.SecretManagerServiceClient() 等)放入其中?
  • 是的,函数定义之上和导入之下的所有内容都应该放在那个条件块中。

标签: python unit-testing monkeypatching


【解决方案1】:

有关使用unittest 修补和模拟来模拟 Google API 调用并返回模拟结果的工作示例,请参阅我对此问题的回答: How to Mock a Google API Library with Python 3.7 for Unit Testing

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-24
    • 2018-08-05
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多