Failed to make fun of urllib2.urlopen using Python mock.patch

Below is a code snippet of my api.py module

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

I am trying to make fun of urllib2.urlopen in the unittest above module. I wrote

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

After running unittest, I get an exception

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

What am I missing? Please help me.

+5
source share
1 answer

You are fixing the wrong things: see Where to fix .

In api.py on

 from urllib2 import urlopen from urllib2 import Request 

you create a local link to urlopen and Request in your file. In mock.patch('urllib2.urlopen') you fix the original link and leave api.py untouched.

So replace your patches with

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

should fix your problem .... but this is not enough.

In the test case, api.Request not used, but urllib2.urlopen() create Request using the fixed version: this is why Request().get_type() is MagicMock .

For a full fix, you must completely change your test. First code:

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

Now clarification ... In your test, you do not call Request() because you only pass the first parameter, so I removed the useless patch. In addition, you are fixing the urlopen function, not the urlopen object, which means that the read() method you want to taunt is the method to return the urlopen() object.

Finally, I add a check to urlopen and autospec=True , which is always good practice.

+7
source

Source: https://habr.com/ru/post/1216516/


All Articles