2015-03-31 6 views
5

का उपयोग कर urllib2.urlopen नकली करने में सक्षम नहीं नीचे मेरी api.py मॉड्यूलपायथन के mock.patch

# -*- coding: utf-8 -*- 

from urllib2 import urlopen 
from urllib2 import Request 

class API: 

    def call_api(self, url, post_data=None, header=None): 
     is_post_request = True if (post_data and header) else False 
     response = None 
     try: 
      if is_post_request: 
       url = Request(url = url, data = post_data, headers = header) 
      # Calling api 
      api_response = urlopen(url) 
      response = api_response.read() 
     except Exception as err: 
      response = err 

     return response 

का एक कोड का टुकड़ा मैं ऊपर मॉड्यूल के unittest में urllib2.urlopen उपहास करने के लिए कोशिश कर रहा हूँ है। मैं

# -*- coding: utf-8 -*- 
# test_api.py 

from unittest import TestCase 
import mock 

from api import API 

class TestAPI(TestCase): 

    @mock.patch('urllib2.Request') 
    @mock.patch('urllib2.urlopen') 
    def test_call_api(self, urlopen, Request): 
     urlopen.read.return_value = 'mocked' 
     Request.get_host.return_value = 'google.com' 
     Request.type.return_value = 'https' 
     Request.data = {} 
     _api = API() 
     assert _api.call_api('https://google.com') == 'mocked' 

लिखा है के बाद मैं unittest चलाने के लिए, मैं एक अपवाद

<urlopen error unknown url type: <MagicMock name='Request().get_type()' id='159846220'>> 

मैं क्या याद आ रही है मिल सकता है? कृपया मेरी मदद करें।

उत्तर

7

आप गलत चीजें पैच कर रहे हैं: Where to patch पर एक नज़र डालें।

api.py में से

from urllib2 import urlopen 
from urllib2 import Request 

आप अपनी फ़ाइल में urlopen और Request के लिए एक स्थानीय संदर्भ पैदा करते हैं। mock.patch('urllib2.urlopen') द्वारा आप मूल संदर्भ पैच कर रहे हैं और api.py के एक छूटे हुए छोड़ दें।

तो,

@mock.patch('api.Request') 
@mock.patch('api.urlopen') 

करके अपने पैच की जगह आपकी समस्या का समाधान करना चाहिए .... लेकिन पर्याप्त नहीं है।

अपने परीक्षण का मामला api.Request में उपयोग किया जाता है नहीं लेकिन urllib2.urlopen() उपयोग के द्वारा समझौता संस्करण एक Request बनाएँ: यही वजह है कि Request().get_type() एक MagicMock है।

एक पूर्ण फिक्स के लिए आपको अपना परीक्षण बिल्कुल बदलना चाहिए। सबसे पहले कोड:

@mock.patch('api.urlopen', autospec=True) 
def test_call_api(self, urlopen): 
    urlopen.return_value.read.return_value = 'mocked' 
    _api = API() 
    self.assertEqual(_api.call_api('https://google.com'), 'mocked') 
    urlopen.assert_called_with('https://google.com') 

अब स्पष्टीकरण ... अपने परीक्षण में आप कहते हैं नहीं Request() क्योंकि आप बस पहले पैरामीटर पारित, तो मैं बेकार पैच हटा दिया है। इसके अलावा आप urlopen फ़ंक्शन को पैच कर रहे हैं और urlopen ऑब्जेक्ट नहीं हैं, जिसका अर्थ है कि read() विधि जिसे आप मॉक करना चाहते हैं, urlopen() कॉल द्वारा ऑब्जेक्ट रिटर्न का एक तरीका है।

अंत में मैं urlopen कॉल और autospec=True पर एक चेक जोड़ता हूं जो हमेशा एक अच्छा अभ्यास है।

+0

मैंने परिवर्तन किए। '_api.call_api ('https://google.com') का मान' 'जो "mocked" से मेल नहीं खाता है। क्यूं कर? अनुलेख मैंने test_api.py – Hussain

+0

में 'assert' के साथ अंतिम पंक्ति को अपडेट किया है मुझे आपके परीक्षण को फिर से लिखना चाहिए .... बहुत अधिक विवरण गलत हैं। –

+0

@ हुसैन अब यह ठीक होना चाहिए –

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