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

如何正确Mock全局作用域中的Python模块变量boto3.client?

如何正确Mock全局作用域中的boto3.client

问题根源

你的原始ecr.py中,client = boto3.client('ecr')属于模块级全局变量,在模块被Python解释器加载时就会执行并实例化真实的ECR客户端。而测试代码中的mock.patch('boto3.client')是在测试函数运行时才生效,此时全局client已经被创建,mock无法回溯修改已存在的实例,导致测试不生效。

解决方案1:直接Mock模块内的全局client变量

不需要修改业务代码,直接针对被测模块里的全局client对象进行mock,替换它的方法行为:

import unittest
from unittest import mock

from mirror import ecr_service

class TestEcrService(unittest.TestCase):
    def test_get_tags(self):
        # 替换ecr_service模块里的全局client变量为mock对象
        with mock.patch('mirror.ecr_service.client') as mock_client:
            # 预设list_images方法的返回值
            mock_client.list_images.return_value = {
                'imageIds': [
                    {'imageTag': 'v2.33.4'},
                    {'imageTag': 'v2.33.3'}
                ]
            }
            tags = ecr_service.get_tags('prometheus')
        self.assertEqual(['v2.33.4', 'v2.33.3'], tags)

这种方式跳过了对boto3.client的mock,直接针对已存在的全局客户端实例做行为模拟,能快速适配原有代码结构。

解决方案2:重构业务代码(你已采用的方案)

将客户端实例化逻辑从全局移到函数内部,这样每次调用get_tags时都会重新调用boto3.client,此时测试中的mock.patch('boto3.client')就能生效:

重构后的ecr.py

import boto3

def get_tags(repository):
    response = boto3.client('ecr').list_images(repositoryName=repository)
    tags = [image['imageTag'] for image in response['imageIds']]
    return tags

对应的测试代码

import unittest
from unittest import mock

from mirror import ecr_service
from tests import fake_requests

class TestEcrService(unittest.TestCase):
    def test_get_tags(self):
        with mock.patch('boto3.client', fake_requests.fake_client):
            tags = ecr_service.get_tags('prometheus')
        self.assertEqual(['v2.33.4', 'v2.33.3'], tags)

这种方案从根源上消除了全局状态带来的测试不确定性,让代码更易于维护和扩展,是更推荐的长期解决方案。


内容的提问来源于stack exchange,提问作者Andre Fagundes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 10:20:39