简体   繁体   English

如何在单元测试中正确修补boto3呼叫

[英]How to properly patch boto3 calls in unit test

I'm new to Python unit testing, and I want to mock calls to the boto3 3rd party library. 我是Python单元测试的新手,我想模拟对boto3 3rd party库的调用。 Here's my stripped down code: 这是我的简化代码:

real_code.py: real_code.py:

import boto3

def temp_get_variable(var_name):
  return boto3.client('ssm').get_parameter(Name=var_name)['Parameter']['Value']

test_real_code.py: test_real_code.py:

import unittest
from datetime import datetime
from unittest.mock import patch

import real_code

class TestRealCode(unittest.TestCase):

    @patch('patching_config.boto3.client')
    def test_get_variable(self, mock_boto_client):

        response = {
            'Parameter': {
                'Name': 'MyTestParameterName',
                'Type': 'String',
                'Value': 'myValue',
                'Version': 123,
                'Selector': 'asdf',
                'SourceResult': 'asdf',
                'LastModifiedDate': datetime(2019, 7, 16),
                'ARN': 'asdf'
            }
        }

        mock_boto_client.get_variable.return_value = response

        result_value = real_code.get_variable("MyTestParameterName")

        self.assertEqual("myValue", result_value)

When I run it the test fails with 当我运行它时,测试失败

Expected :myValue
Actual   :<MagicMock name='client().get_parameter().__getitem__().__getitem__()' id='2040071816528'>

What am I doing wrong? 我究竟做错了什么? I thought by setting mock_boto_client.get_variable.return_value = response it would mock out the call and return my canned response instead. 我认为通过设置mock_boto_client.get_variable.return_value = response ,它将模拟呼叫并返回我的罐头响应。 I don't understand why I am getting a MagicMock object instead of the return value I tried to set. 我不明白为什么我得到了MagicMock对象而不是我试图设置的返回值。 I'd like to set up my test so that when the call to get_parameter is made with specific parameters, the mock returns the canned response I specified in the test. 我想设置测试,以便在使用特定参数调用get_parameter时,该模拟返回我在测试中指定的固定响应。

There are two issues with your test code. 您的测试代码有两个问题。 The first is that when your mock object mock_boto_client called, it returns a new mock object. 第一个是当您的模拟对象mock_boto_client调用时,它将返回一个新的模拟对象。 This means that the object that get_parameter() is being called on is different than the one you are attempting to set a return value on. 这意味着正在调用get_parameter()的对象与您尝试在其上设置返回值的对象不同。 You can have it return itself with the following: 您可以使用以下命令返回自身:

mock_boto_client.return_value = mock_boto_client

You can also use a different mock object: 您还可以使用其他模拟对象:

foo = MagicMock()
mock_boto_client.return_value = foo

The second issue that you have is that you are mocking the wrong method call. 您遇到的第二个问题是您在模拟错误的方法调用。 mock_boto_client.get_variable.return_value should be mock_boto_client.get_parameter.return_value . mock_boto_client.get_variable.return_value应该是mock_boto_client.get_parameter.return_value Here is the test updated and working: 这是已更新且可以正常运行的测试:

import unittest
from datetime import datetime
from unittest.mock import patch

import real_code

class TestRealCode(unittest.TestCase):

    @patch('boto3.client')
    def test_get_variable(self, mock_boto_client):

        response = {
            'Parameter': {
                'Name': 'MyTestParameterName',
                'Type': 'String',
                'Value': 'myValue',
                'Version': 123,
                'Selector': 'asdf',
                'SourceResult': 'asdf',
                'LastModifiedDate': datetime(2019, 7, 16),
                'ARN': 'asdf'
            }
        }

        mock_boto_client.return_value = mock_boto_client
        mock_boto_client.get_parameter.return_value = response

        result_value = real_code.get_variable("MyTestParameterName")

        self.assertEqual("myValue", result_value)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM