You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mock Google Cloud Storage时如何禁用认证以解决凭证错误

问题描述

我在Python中编写了如下Google Cloud Storage的Mock代码,用于测试使用存储桶的业务逻辑(Mock的Blob会返回含换行分隔ID的字节串):

from google.cloud import storage


class MockBlob:
    def download_as_string(self) -> bytes:
        return bytes("\n".join(INPUT_IDS), "utf-8")


class MockBucket:
    def get_blob(self, path: str) -> MockBlob:
        return MockBlob()


class MockStorageClient(storage.Client):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def _require_client_info(self, client_info=None):
        pass

    def _require_virtual(self):
        pass

    def get_bucket(self, bucket_or_name: str):
        return MockBucket()

运行时触发如下错误:

.venv/lib/python3.8/site-packages/google/cloud/storage/client.py:173: in __init__
    super(Client, self).__init__(
.venv/lib/python3.8/site-packages/google/cloud/client/__init__.py:320: in __init__
    _ClientProjectMixin.__init__(self, project=project, credentials=credentials)
.venv/lib/python3.8/site-packages/google/cloud/client/__init__.py:268: in __init__
    project = self._determine_default(project)
.venv/lib/python3.8/site-packages/google/cloud/client/__init__.py:287: in _determine_default
    return _determine_default_project(project)
.venv/lib/python3.8/site-packages/google/cloud/_helpers/__init__.py:152: in _determine_default_project
    _, project = google.auth.default()
.venv/lib/python3.8/site-packages/google/auth/_default.py:615: in default
    credentials, project_id = checker()
.venv/lib/python3.8/site-packages/google/auth/_default.py:608: in <lambda>
    lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id),
.venv/lib/python3.8/site-packages/google/auth/_default.py:228: in _get_explicit_environ_credentials
    credentials, project_id = load_credentials_from_file(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

filename = '', scopes = None, default_scopes = None, quota_project_id = None, request = None

    def load_credentials_from_file(
        filename, scopes=None, default_scopes=None, quota_project_id=None, request=None
    ):
        """Loads Google credentials from a file.
    
        The credentials file must be a service account key, stored authorized
        user credentials, external account credentials, or impersonated service
        account credentials.
    
        Args:
            filename (str): The full path to the credentials file.
            scopes (Optional[Sequence[str]]): The list of scopes for the credentials. If
                specified, the credentials will automatically be scoped if
                necessary
            default_scopes (Optional[Sequence[str]]): Default scopes passed by a
                Google client library. Use 'scopes' for user-defined scopes.
            quota_project_id (Optional[str]):  The project ID used for
                quota and billing.
            request (Optional[google.auth.transport.Request]): An object used to make
                HTTP requests. This is used to determine the associated project ID
                for a workload identity pool resource (external account credentials).
                If not specified, then it will use a
                google.auth.transport.requests.Request client to make requests.
    
        Returns:
            Tuple[google.auth.credentials.Credentials, Optional[str]]: Loaded
                credentials and the project ID. Authorized user credentials do not
                have the project ID information. External account credentials project
                IDs may not always be determined.
    
        Raises:
            google.auth.exceptions.DefaultCredentialsError: if the file is in the
                wrong format or is missing.
        """
        if not os.path.exists(filename):
>           raise exceptions.DefaultCredentialsError(
                "File {} was not found.".format(filename)
            )
E           google.auth.exceptions.DefaultCredentialsError: File  was not found.

.venv/lib/python3.8/site-packages/google/auth/_default.py:116: DefaultCredentialsError

请问如何禁用Google Cloud认证,以解决该凭证错误问题?

解决方案

方法1:修改MockClient初始化逻辑跳过认证

直接在MockStorageClient的__init__方法中强制设置credentials=None和指定测试用的project,跳过GCS客户端的默认凭证检测流程:

class MockStorageClient(storage.Client):
    def __init__(self, *args, **kwargs):
        # 强制覆盖参数,禁用认证检测
        kwargs["credentials"] = None
        kwargs["project"] = "test-project"
        super().__init__(*args, **kwargs)

    def _require_client_info(self, client_info=None):
        pass

    def _require_virtual(self):
        pass

    def get_bucket(self, bucket_or_name: str):
        return MockBucket()

之后直接实例化MockStorageClient即可,无需额外传参。

方法2:使用unittest.mock直接Mock整个客户端

无需继承storage.Client,用Python自带的unittest.mock替换客户端实现,完全隔离真实GCS逻辑:

from unittest.mock import Mock, patch
from google.cloud import storage

def test_business_logic():
    # Mock Blob对象
    mock_blob = Mock()
    mock_blob.download_as_string.return_value = bytes("\n".join(INPUT_IDS), "utf-8")
    
    # Mock Bucket对象
    mock_bucket = Mock()
    mock_bucket.get_blob.return_value = mock_blob
    
    # Mock Client对象
    mock_client = Mock()
    mock_client.get_bucket.return_value = mock_bucket
    
    # 替换storage.Client为mock实例
    with patch("google.cloud.storage.Client", return_value=mock_client):
        # 执行你的业务逻辑代码
        your_business_function()

这种方式更简洁,且完全避免触发任何GCS认证相关逻辑。

方法3:通过环境变量临时跳过认证

在运行测试前设置环境变量,强制跳过凭证检测:

  • Linux/macOS终端:
    export GOOGLE_APPLICATION_CREDENTIALS=""
    export GOOGLE_CLOUD_PROJECT="test-project"
    
  • Windows PowerShell:
    $env:GOOGLE_APPLICATION_CREDENTIALS = ""
    $env:GOOGLE_CLOUD_PROJECT = "test-project"
    

不过该方法仅适合临时场景,推荐优先使用前两种代码层面的方案。

内容的提问来源于stack exchange,提问作者S.MC.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 18:42:03