2015-03-31 21 views
5

Poniżej znajduje się fragment kodu mojego modułu api.pyNie mógł kpić urllib2.urlopen użyciu Pythona 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 

Próbuję mock urllib2.urlopen w unittest powyższego modułu. Pisałem

# -*- 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' 

Po uruchomieniu unittest, otrzymuję wyjątek

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

Czego mi brakuje? Proszę pomóż mi.

Odpowiedz

7

Naprawiasz niewłaściwe rzeczy: spójrz na numer Where to patch.

W api.py przez

from urllib2 import urlopen 
from urllib2 import Request 

utworzyć lokalną odniesienie do urlopen i Request w pliku. Pod numerem mock.patch('urllib2.urlopen') naprawiasz oryginalne odniesienie i pozostawiasz nietknięte jeden numer api.py.

tak, wymień swoje poprawki przez

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

powinno rozwiązać problem .... ale to za mało.

W twoim przypadku testowego api.Request nie są używane, ale urllib2.urlopen()Request utworzyć przy użyciu wersji połatany: dlatego Request().get_type() jest MagicMock.

Aby uzyskać kompletną poprawkę, należy w ogóle zmienić test. Pierwszy kod:

@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') 

Teraz wyjaśnienie ... W swoim badaniu ty nie nazywaj Request() ponieważ przechodzą tylko pierwszy parametr, więc usunęliśmy bezużyteczną poprawkę. Co więcej, łatasz obiekt urlopen, a nie obiekt urlopen, co oznacza, że ​​metoda read(), którą chcesz wyśmiewać, jest metodą zwracania obiektu przez wywołanie urlopen().

Wreszcie dodaję czek na rozmowie urlopen i autospec=True, która jest zawsze dobrą praktyką.

+0

Wprowadziłem zmiany. Wartością '_api.call_api ('https://google.com')' jest '' który nie pasuje do "wyśmiewanego". Czemu? P.S. Zaktualizowałem ostatnią linię z 'assert' w test_api.py – Hussain

+0

Powinienem napisać ponownie twój test .... Zbyt wiele szczegółów jest błędnych. –

+0

@Hussain teraz powinno być OK –

Powiązane problemy