首页 > 编程问答 >当值来自函数 python unittest 时,如何模拟全局变量

当值来自函数 python unittest 时,如何模拟全局变量

时间:2024-07-21 04:07:00浏览次数:12  
标签:python python-unittest python-unittest.mock

我必须在 python 中模拟全局变量,但变量值来自另一个函数。当我导入文件时,这个函数正在运行,但我想要那里的模拟值。

secrets.py

import traceback
import logging
import boto3
import os
import json


logger = logging.getLogger()
logger.setLevel(logging.INFO)

secret_name = os.environ['SECRETS_NAME']
region_name = os.environ['AWS_REGION']
config_secret = dict()

def init_config_secret():

    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )

    try:

        config_secret_value = client.get_secret_value(SecretId=secret_name)

        if 'SecretString' in config_secret_value:
            global config_secret
            config_secret = json.loads(config_secret_value['SecretString'])

        return config_secret
    except Exception as e:
        logger.error('Error while retrieving secrets')
        traceback.print_exc()


def get_config_secret():
    if not bool(config_secret):
        return init_config_secret()
    else:
        return config_secret


if __name__ == '__main__':
    get_config_secret()

request_auth.py

import requests
from secrets import get_config_secret
from datetime import datetime, timedelta

config = get_config_secret()

print(f'config: {config}')

token = None

def verifySSL() :
    return True


def get_api_root_url():
    return config["url"]


def build_request_header(access_token, content_type):

    return {
        "authorization" : access_token,
        "Content-Type" : content_type
    }


def get_access_token():
    global token
    if token is None:
        acquire_token()
    elif token["expiry"] < datetime.now():
        acquire_token()

    return token["authToken"]


def acquire_token():
    auth_payload = {
        "grant_type" : "client_credentials",
        "client_id" : config["id"]
    }
    response = requests.post(config["url"], data = auth_payload, verify = verifySSL())
    # print(response.json())

    global token
    token= dict()
    token["authToken"] = response.json()["access_token"]
    token["expiry"] = datetime.now() + timedelta(minutes = 10)

test_request_auth.py

import json, sys
import unittest, os
from unittest.mock import patch, Mock
from unittest import mock


from request_auth import *  


class TestRequestAuth(unittest.TestCase):

    @patch("request_auth.config", {"test": "test"})
    @patch("request_auth.get_config_secret")
    def test_get_api_root_url(self, mock_get_config_secret):
        mock_get_config_secret.return_value = {"url": "test"}
        self.assertEqual(get_api_root_url(), "https://test.test.com/")

我尝试了这种方式,但不工作不确定需要做什么。 有人可以帮忙吗?


在测试中遇到的问题是, config 变量是在导入 request_auth 模块时被初始化的,该操作发生在的测试函数运行之前。这意味着的补丁无法生效,因为 config 变量已经被赋值了。

为了解决这个问题,可以将 config 变量的初始化延迟到需要使用它的时候。以下是如何修改的代码来实现这一点:

request_auth.py:

import requests
from secrets import get_config_secret
from datetime import datetime, timedelta

# 不要在这里直接初始化 config
# config = get_config_secret()

# ... 其他代码 ...

def get_api_root_url():
    # 在需要使用 config 时再调用 get_config_secret()
    config = get_config_secret()
    return config.get("url", "")

# ... 其他代码 ...

test_request_auth.py:

import unittest
from unittest.mock import patch
from request_auth import get_api_root_url, get_config_secret  # 导入 get_config_secret

class TestRequestAuth(unittest.TestCase):

    @patch("request_auth.get_config_secret")
    def test_get_api_root_url(self, mock_get_config_secret):
        mock_get_config_secret.return_value = {"url": "https://test.test.com/"}
        self.assertEqual(get_api_root_url(), "https://test.test.com/")

在这个修改后的代码中:

  1. 我们从 request_auth.py 中移除了 config = get_config_secret() 这一行,这样就不会在模块导入时初始化 config
  2. 我们在 get_api_root_url 函数内部调用 get_config_secret() ,以确保在需要使用 config 变量时才获取它的值。
  3. 在测试代码中,我们直接 mock request_auth.get_config_secret 函数,这样就可以控制 get_api_root_url 函数内部获取到的 config 值。

通过这种方式,可以成功地模拟 get_config_secret 函数的返回值,从而在测试中控制 config 变量的值。

标签:python,python-unittest,python-unittest.mock
From: 78365878

相关文章

  • 使用 python print 和 gdb 时出现 BrokenPipeError
    我正在尝试在Linux中运行应用程序并使用Python生成输入:python3-c'print(".....")'|./someapp但出现下一个错误:Exceptionignoredin:<_io.TextIOWrappername='<stdout>'mode='w'encoding='utf-8'>BrokenPipeError:......
  • python 舰队容器
    我正在尝试使用容器在flet中制作一个菜单,它应该是半透明的,但其中的项目不是。我尝试将opacity=1分配给元素,但没有成功-它们与容器一样透明感谢任何帮助我的代码:nickname=ft.TextField(label="xxx",hint_text="xxx")column=ft.Column(controls=[nickname......
  • Python应用程序跨子包共享的配置文件
    我正在构建一个应用程序来控制一些硬件。我在包中实现了不同类型的硬件:电机和测量设备。我的文件结构如下:name_of_my_app/__init__.pymain.pyconfig.iniCONFIG.pymotors/__init__.pyone_kind_of_motor.pymeasurement_devices/......
  • python中时间序列数据的梯度计算
    我正在尝试编写一个函数,它可以从最适合下面的线返回梯度dataframe在浏览了谷歌的几个资源之后,我仍然不确定这是如何完成的。我明白最佳拟合线的计算公式为:y=mx+b将因变量(y)设置为foos,将自变量(x)设置为DateTimeDatafram......
  • 调试用 C 编写的 Python 扩展
    我非常熟悉编写C代码,并且很擅长编写Python代码。我正在尝试学习如何用C编写可以从OSX10.15.7上的Python-3.9.X调用的模块。我已经得到了几个“helloworld”类型的示例,但是对于复杂的示例,我正在努力弄清楚如何调试我编写的C扩展。MWE:src/add.c//......
  • 具有块大小选项的 Python pandas read_sas 因索引不匹配而失败并出现值错误
    我有一个非常大的SAS文件,无法容纳在我的服务器内存中。我只需要转换为镶木地板格式的文件。为此,我使用pandas中chunksize方法的read_sas选项分块读取它。它主要是在工作/做它的工作。除此之外,一段时间后它会失败并出现以下错误。此特定SAS文件有794......
  • 使用 requests 包 python 时打开文件太多
    我正在使用Pythonrequests包向API发出大量请求。然而,在某些时候,我的程序由于“打开的文件太多”而崩溃。当我明确关闭我的会话时,我真的不知道这是怎么回事。我使用以下代码:importrequestsimportmultiprocessingimportnumpyasnps=requests.session()s.keep......
  • Python 是一种选择性解释语言吗?为什么下面的代码不起作用?
    由于程序是从上到下运行的,为什么下面的代码不执行块中的第一行就直接抛出错误?if5>2:print("TwoislessthanFive!")print("Fiveisgreaterthantwo!")错误:文件“/Users/____/Desktop/Pythonpractise/practise.py”,第3行print("五比二大!")Indentati......
  • 裁剪时间变量 Python Matplotlib Xarray
    我不确定这是否是一个愚蠢的问题,但我想按时间变量剪辑.nc文件。我在xarray中打开了数据集,但以下ds.sel行(之前已运行)仅返回错误。ds=xr.open_dataset('/Users/mia/Desktop/RMP/data/tracking/mcs_tracks_2015_11.nc')selected_days=ds.sel(time=slice('2015-11-22',......
  • 用于匹配两个数据列表中的项目的高效数据结构 - python
    我有两个列表,其中一个列表填充ID,另一个列表填充进程名称。多个进程名称可以共享一个ID。我希望能够创建一个可以使用特定ID的数据结构,然后返回与该ID关联的进程列表。我还希望能够使用特定的进程名称并返回与其连接的ID列表。我知道我可以为此创建一个字典,但是I......