在python中模拟或修补类实例变量?

时间:2019-10-19 21:30:02

标签: python unit-testing boto3

所以我在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()的任何提示?

1 个答案:

答案 0 :(得分:1)

boto3.client返回基于第一个参数的动态创建类的实例(请参见source),因此您不能使用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