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.
相关产品推荐
相关产品推荐

