首页 > 解决方案 > 在 python 中模拟或修补类实例变量?

问题描述

所以我在 file/s3.py 中有一个类 S3,它具有以下初始化:

class S3:
    def __init__(self):
        self.s3_client = boto3.client("s3")

    def get_object(self):
        s3_object = self.s3_client.get_object()
        return s3_object

如您所见,boto3.client 类也有一个名为的方法get_object()。我正在get_object()从另一个文件测试我的自定义方法,但不想实际对 AWS 服务进行 boto3.client 调用。

test.py

class TestS3Class(unittest.TestCase):
    """TestCase for file/s3.py"""

    def setUp(self):
        """Creates an instance of the live S3 class for testing"""
        self.s3_test_client = S3()

    @patch('boto3.client')
    def test_get_object(self, mock_client):
        """"""
        mock_client.get_object.return_value = {'key': 'value'}
        self.assertIsInstance(self.s3_test_client.get_object(), dict)

目前我得到AssertionError: None is not an instance of <class 'dict'>了回应,所以我不确定我是否正在修补某些东西,但它绝对没有将 boto3.client.get_object() 的返回值设置为字典对象。

关于如何模拟 self.s3_client = boto3.client() 的任何提示?

标签: pythonunit-testingboto3

解决方案


boto3.client根据第一个参数返回一个动态创建的类的实例(参见源代码),因此您不能使用该patch方法,该方法要求目标对象是可导入的。

相反,您可以使用在调用时返回所需字典get_object的对象对客户端的类对象的属性进行猴子修补:Mock

class TestS3Class(unittest.TestCase):
    def setUp(self):
        self.s3_test_client = S3()
        self.s3_test_client.s3_client.__class__.get_object = Mock(return_value={'key': 'value'})

    def test_get_object(self):
        self.assertIsInstance(self.s3_test_client.get_object(), dict)

演示:https ://repl.it/@blhsing/MarriedDeficientNumerator


推荐阅读