2016-05-10 7 views
23

मैं boto3 s3 क्लाइंट ऑब्जेक्ट से फेंकने और अपवाद के लिए सिंगलर विधि का नकल करने की कोशिश कर रहा हूं। लेकिन इस वर्ग के लिए सामान्य के रूप में काम करने के लिए मुझे अन्य सभी तरीकों की आवश्यकता है।मॉकिंग boto3 S3 क्लाइंट विधि पायथन

ImportError: No module named S3 

:

यह तो मैं एक विलक्षण अपवाद परीक्षण परीक्षण कर सकते हैं जब और त्रुटि एक upload_part_copy

1 प्रयास

import boto3 
from mock import patch 

with patch('botocore.client.S3.upload_part_copy', side_effect=Exception('Error Uploading')) as mock: 
    client = boto3.client('s3') 
    # Should return actual result 
    o = client.get_object(Bucket='my-bucket', Key='my-key') 
    # Should return mocked exception 
    e = client.upload_part_copy() 

हालांकि इस निम्न त्रुटि देता प्रदर्शन होता है दूसरा प्रयास

botocore.client.py स्रोत कोड को देखने के बाद मैंने पाया कि यह कुछ चालाक कर रहा है और विधि upload_part_copy मौजूद नहीं है। मैंने पाया कि यह बजाय BaseClient._make_api_call कॉल करने के लिए तो मैं उपहास करने के लिए कि

import boto3 
from mock import patch 

with patch('botocore.client.BaseClient._make_api_call', side_effect=Exception('Error Uploading')) as mock: 
    client = boto3.client('s3') 
    # Should return actual result 
    o = client.get_object(Bucket='my-bucket', Key='my-key') 
    # Should return mocked exception 
    e = client.upload_part_copy() 

यह एक अपवाद फेंकता है, लेकिन एक अपवाद फेंकता है की कोशिश की है ... लेकिन get_object जिस पर मैं बचना चाहते हैं।

इस बारे में कोई विचार है कि मैं केवल upload_part_copy विधि पर अपवाद कैसे फेंक सकता हूं?

उत्तर

8

जैसे ही मैंने यहां पोस्ट किया, मैं एक समाधान के साथ आने में कामयाब रहा। यहाँ यह आशा है यह मदद करता है :)

import botocore 
from botocore.exceptions import ClientError 
from mock import patch 
import boto3 

orig = botocore.client.BaseClient._make_api_call 

def mock_make_api_call(self, operation_name, kwarg): 
    if operation_name == 'UploadPartCopy': 
     parsed_response = {'Error': {'Code': '500', 'Message': 'Error Uploading'}} 
     raise ClientError(parsed_response, operation_name) 
    return orig(self, operation_name, kwarg) 

with patch('botocore.client.BaseClient._make_api_call', new=mock_make_api_call): 
    client = boto3.client('s3') 
    # Should return actual result 
    o = client.get_object(Bucket='my-bucket', Key='my-key') 
    # Should return mocked exception 
    e = client.upload_part_copy() 

Jordan Philips also posted a great solutionbotocore.stub.Stubber वर्ग का उपयोग कर। एक क्लीनर समाधान के दौरान मैं विशिष्ट संचालन का नकल करने में सक्षम नहीं था।

+2

यह बहुत उपयोगी है। मुझे यह महसूस करने में थोड़ी देर लग गई कि बहुत से बोटो 3 क्लाइंट प्रभावी ढंग से [रनटाइम पर जेनरेट किए गए हैं] (https://boto3.readthedocs.io/en/latest/guide/new.html#major-features), और ऐसे में , सीधे मजाक नहीं किया जा सकता है। – rumdrums

32

बोटोकोर का क्लाइंट स्टबर है जिसका उपयोग आप इस उद्देश्य के लिए कर सकते हैं: docs

यहाँ में एक त्रुटि डालने की एक उदाहरण है:

import boto3 
from botocore.stub import Stubber 

client = boto3.client('s3') 
stubber = Stubber(client) 
stubber.add_client_error('upload_part_copy') 
stubber.activate() 

# Will raise a ClientError 
client.upload_part_copy() 

यहाँ में एक सामान्य प्रतिक्रिया डालने का एक उदाहरण है साथ ही, stubber अब एक संदर्भ में प्रयोग किया जा सकता है।। यह ध्यान रखना महत्वपूर्ण है कि स्टबर सुरक्षित होगा, जहां तक ​​यह सक्षम है, कि आपकी प्रदत्त प्रतिक्रिया मेल खाती है कि सेवा वास्तव में क्या लौट जाएगी। यह सही नहीं है, लेकिन यह आपको कुल बकवास प्रतिक्रियाओं को सम्मिलित करने से बचाएगा।

import boto3 
from botocore.stub import Stubber 

client = boto3.client('s3') 
stubber = Stubber(client) 
list_buckets_response = { 
    "Owner": { 
     "DisplayName": "name", 
     "ID": "EXAMPLE123" 
    }, 
    "Buckets": [{ 
     "CreationDate": "2016-05-25T16:55:48.000Z", 
     "Name": "foo" 
    }] 
} 
expected_params = {} 
stubber.add_response('list_buckets', list_buckets_response, expected_params) 

with stubber: 
    response = client.list_buckets() 

assert response == list_buckets_response 
+0

अच्छा धन्यवाद @ जोर्डन, मुझे यह क्यों नहीं मिला! – ptimson

+0

ठीक है, क्योंकि यह बोटोकोर में है, आपको बॉटोकोर दस्तावेज़ों में देखना होगा, और बहुत से नहीं। यह भी काफी हाल ही में है। –

+0

क्लाइंट.अपलोड_part_copy() क्लाइंट एरर क्यों बढ़ाएगा? –

5

यहाँ कि unittest एक सरल अजगर का एक उदाहरण नकली ग्राहक = boto3.client ('EC2') API कॉल करने के लिए इस्तेमाल किया जा सकता उम्मीद है कि मदद करता है है ...

import boto3 

class MyAWSModule(): 
    def __init__(self): 
     client = boto3.client('ec2') 
     tags = client.describe_tags(DryRun=False) 


class TestMyAWSModule(unittest.TestCase): 
    @mock.patch("boto3.client.get_tags") 
    @mock.patch("boto3.client") 
    def test_open_file_with_existing_file(self, mock_boto_client, mock_describe_tags): 
     mock_boto_client.return_value = mock_get_tags_response 
     my_aws_module = MyAWSModule() 

     mock_boto_client.assert_call_once('ec2') 
     mock_describe_tags.assert_call_once_with(DryRun=False) 

mock_get_tags_response = { 
    'Tags': [ 
     { 
      'ResourceId': 'string', 
      'ResourceType': 'customer-gateway', 
      'Key': 'string', 
      'Value': 'string' 
     }, 
    ], 
'NextToken': 'string' 
} 

+0

मैं वैश्विक क्लाइंट या संसाधन ऑब्जेक्ट का प्रबंधन कैसे कर सकता हूं? इसे मजाक नहीं किया जा सकता क्योंकि इसका आविष्कार नकली सेटअप से पहले होता है। – pt12lol

+0

'test_open_file_with_existing_file' की पहली पंक्ति 'mock_describe_tags.return_value = mock_get_tags_response' नहीं होनी चाहिए? 'mock_boto_client' के बजाय? – daniele

संबंधित मुद्दे