-
-
Save lastorset/075a8d4db8937509c33f4a36c6e3de7f to your computer and use it in GitHub Desktop.
Google AppEngine URLFetch in Unit Tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from google.appengine.api import apiproxy_stub, apiproxy_stub_map, urlfetch | |
from google.appengine.ext import testbed | |
import unittest | |
class FetchServiceMock(apiproxy_stub.APIProxyStub): | |
""" | |
Example:: | |
with FetchServiceMock(content='A MOCKERY', status_code=200) as fetch_mock: | |
ret = main.method('amok') | |
self.assertEquals('http://amok.com', fetch_mock.request.url()) | |
self.assertEquals('A MOCKERY', ret) | |
Inspired by https://gist.github.com/kesor/1179782 | |
""" | |
def __init__( | |
self, content='', status_code=500, headers=None, | |
final_url=None, content_was_truncated=False): | |
""" | |
:param final_url: URL after redirects. | |
""" | |
# type: (basestring, int, Optional[Mapping], Optional[basestring], bool) -> None | |
super(FetchServiceMock, self).__init__(testbed.URLFETCH_SERVICE_NAME) | |
self.return_values = { | |
'content': content, | |
'statuscode': status_code, | |
'headers': headers if headers else {}, | |
'finalurl': final_url, | |
'contentwastruncated': content_was_truncated, | |
} | |
def __enter__(self): | |
apiproxy_stub_map.apiproxy.ReplaceStub( | |
testbed.URLFETCH_SERVICE_NAME, self) | |
return self | |
def __exit__(self, exc_type, exc_val, exc_tb): | |
complaining_mock = FetchServiceMock( | |
content='Error: {} was reset. You must either mock urlfetch again ' | |
'or run Testbed.init_urlfetch_stub'.format(FetchServiceMock.__name__), | |
status_code=418) | |
apiproxy_stub_map.apiproxy.ReplaceStub( | |
testbed.URLFETCH_SERVICE_NAME, complaining_mock) | |
def _Dynamic_Fetch(self, request, response): | |
rv = self.return_values | |
response.set_content(rv['content']) | |
response.set_statuscode(rv['statuscode']) | |
for header_key, header_value in rv['headers'].iteritems(): | |
new_header = response.add_header() # prototype for a header | |
new_header.set_key(header_key) | |
new_header.set_value(header_value) | |
response.set_finalurl(rv['finalurl'] or request.url) | |
response.set_contentwastruncated(rv['contentwastruncated']) | |
# allow to query the object after it is used | |
self.request = request | |
self.response = response | |
class TestFetchServiceMock(unittest.TestCase): | |
def setUp(self): | |
self.testbed = testbed.Testbed() | |
self.testbed.activate() | |
self.testbed.init_urlfetch_stub() | |
def test_mocking(self): | |
with FetchServiceMock(self.testbed, 'A MOCKERY') as fetch_mock: | |
fetched = urlfetch.fetch('http://httpstat.us/200') | |
self.assertEqual(fetched.content, 'A MOCKERY') | |
self.assertEqual(fetched.status_code, 500) | |
self.assertEqual('http://httpstat.us/200', fetch_mock.request.url()) | |
def test_mock_resets(self): | |
with FetchServiceMock(self.testbed, 'A MOCKERY'): | |
active_stub = apiproxy_stub_map.apiproxy.GetStub( | |
testbed.URLFETCH_SERVICE_NAME) | |
self.assertIsInstance(active_stub, FetchServiceMock) | |
active_stub = apiproxy_stub_map.apiproxy.GetStub( | |
testbed.URLFETCH_SERVICE_NAME) | |
self.assertNotIsInstance(active_stub, FetchServiceMock) | |
# Enable to actually call the Internet | |
if False: | |
fetched2 = urlfetch.fetch('http://httpstat.us/200') | |
self.assertEqual(fetched2.content, '200 OK') | |
self.assertEqual(fetched2.status_code, 200) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is it possible to set content type like 'application/json'?