This repository has been archived by the owner on Nov 5, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 430
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #585 from dhermes/remove-httplib2-from-unit-tests
Removes usage of httplib2 in unit tests.
- Loading branch information
Showing
7 changed files
with
222 additions
and
235 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,6 @@ | |
from google.appengine.ext import db | ||
from google.appengine.ext import ndb | ||
from google.appengine.ext import testbed | ||
import httplib2 | ||
import mock | ||
from six.moves import urllib | ||
import unittest2 | ||
|
@@ -42,11 +41,19 @@ | |
from oauth2client import client | ||
from oauth2client import clientsecrets | ||
from oauth2client.contrib import appengine | ||
from ..http_mock import CacheMock | ||
from .. import http_mock | ||
|
||
__author__ = '[email protected] (Joe Gregorio)' | ||
|
||
DATA_DIR = os.path.join(os.path.dirname(__file__), '..', 'data') | ||
DEFAULT_RESP = """\ | ||
{ | ||
"access_token": "foo_access_token", | ||
"expires_in": 3600, | ||
"extra": "value", | ||
"refresh_token": "foo_refresh_token" | ||
} | ||
""" | ||
|
||
|
||
def datafile(filename): | ||
|
@@ -75,22 +82,6 @@ def __call__(self): | |
return None | ||
|
||
|
||
class Http2Mock(object): | ||
"""Mock httplib2.Http""" | ||
status = 200 | ||
content = { | ||
'access_token': 'foo_access_token', | ||
'refresh_token': 'foo_refresh_token', | ||
'expires_in': 3600, | ||
'extra': 'value', | ||
} | ||
|
||
def request(self, token_uri, method, body, headers, *args, **kwargs): | ||
self.body = body | ||
self.headers = headers | ||
return self, json.dumps(self.content) | ||
|
||
|
||
class TestAppAssertionCredentials(unittest2.TestCase): | ||
account_name = "[email protected]" | ||
signature = "signature" | ||
|
@@ -139,7 +130,7 @@ def test_raise_correct_type_of_exception(self): | |
|
||
scope = 'http://www.googleapis.com/scope' | ||
credentials = appengine.AppAssertionCredentials(scope) | ||
http = httplib2.Http() | ||
http = http_mock.HttpMock(data=DEFAULT_RESP) | ||
with self.assertRaises(client.AccessTokenRefreshError): | ||
credentials.refresh(http) | ||
|
||
|
@@ -155,7 +146,7 @@ def test_get_access_token_on_refresh(self): | |
"http://www.googleapis.com/scope", | ||
"http://www.googleapis.com/scope2"] | ||
credentials = appengine.AppAssertionCredentials(scope) | ||
http = httplib2.Http() | ||
http = http_mock.HttpMock(data=DEFAULT_RESP) | ||
credentials.refresh(http) | ||
self.assertEqual('a_token_123', credentials.access_token) | ||
|
||
|
@@ -168,7 +159,7 @@ def test_get_access_token_on_refresh(self): | |
scope = ('http://www.googleapis.com/scope ' | ||
'http://www.googleapis.com/scope2') | ||
credentials = appengine.AppAssertionCredentials(scope) | ||
http = httplib2.Http() | ||
http = http_mock.HttpMock(data=DEFAULT_RESP) | ||
credentials.refresh(http) | ||
self.assertEqual('a_token_123', credentials.access_token) | ||
self.assertEqual( | ||
|
@@ -184,7 +175,7 @@ def test_custom_service_account(self): | |
autospec=True) as get_access_token: | ||
credentials = appengine.AppAssertionCredentials( | ||
scope, service_account_id=account_id) | ||
http = httplib2.Http() | ||
http = http_mock.HttpMock(data=DEFAULT_RESP) | ||
credentials.refresh(http) | ||
|
||
self.assertEqual('a_token_456', credentials.access_token) | ||
|
@@ -370,7 +361,7 @@ def test_validate(self): | |
|
||
|
||
def _http_request(*args, **kwargs): | ||
resp = httplib2.Response({'status': '200'}) | ||
resp = http_mock.ResponseMock() | ||
content = json.dumps({'access_token': 'bar'}) | ||
|
||
return resp, content | ||
|
@@ -630,12 +621,9 @@ def get(self, *args, **kwargs): | |
}) | ||
self.current_user = user_mock() | ||
users.get_current_user = self.current_user | ||
self.httplib2_orig = httplib2.Http | ||
httplib2.Http = Http2Mock | ||
|
||
def tearDown(self): | ||
self.testbed.deactivate() | ||
httplib2.Http = self.httplib2_orig | ||
|
||
def test_in_error(self): | ||
# NOTE: This branch is never reached. _in_error is not set by any code | ||
|
@@ -655,7 +643,9 @@ def test_callback_application(self): | |
app.router.match_routes[0].handler.__name__, | ||
'OAuth2Handler') | ||
|
||
def test_required(self): | ||
@mock.patch('oauth2client.transport.get_http_object') | ||
def test_required(self, new_http): | ||
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP) | ||
# An initial request to an oauth_required decorated path should be a | ||
# redirect to start the OAuth dance. | ||
self.assertEqual(self.decorator.flow, None) | ||
|
@@ -688,7 +678,7 @@ def test_required(self): | |
response_query = urllib.parse.parse_qs(parts[1]) | ||
response = response_query[ | ||
self.decorator._token_response_param][0] | ||
self.assertEqual(Http2Mock.content, | ||
self.assertEqual(json.loads(DEFAULT_RESP), | ||
json.loads(urllib.parse.unquote(response))) | ||
self.assertEqual(self.decorator.flow, self.decorator._tls.flow) | ||
self.assertEqual(self.decorator.credentials, | ||
|
@@ -736,7 +726,12 @@ def test_required(self): | |
self.assertEqual('http://localhost/oauth2callback', | ||
query_params['redirect_uri'][0]) | ||
|
||
def test_storage_delete(self): | ||
# Check the mocks were called. | ||
new_http.assert_called_once_with() | ||
|
||
@mock.patch('oauth2client.transport.get_http_object') | ||
def test_storage_delete(self, new_http): | ||
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP) | ||
# An initial request to an oauth_required decorated path should be a | ||
# redirect to start the OAuth dance. | ||
response = self.app.get('/foo_path') | ||
|
@@ -772,7 +767,12 @@ def test_storage_delete(self): | |
parse_state_value.assert_called_once_with( | ||
'foo_path:xsrfkey123', self.current_user) | ||
|
||
def test_aware(self): | ||
# Check the mocks were called. | ||
new_http.assert_called_once_with() | ||
|
||
@mock.patch('oauth2client.transport.get_http_object') | ||
def test_aware(self, new_http): | ||
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP) | ||
# An initial request to an oauth_aware decorated path should | ||
# not redirect. | ||
response = self.app.get('http://localhost/bar_path/2012/01') | ||
|
@@ -825,6 +825,9 @@ def test_aware(self): | |
self.should_raise = False | ||
self.assertEqual(None, self.decorator.credentials) | ||
|
||
# Check the mocks were called. | ||
new_http.assert_called_once_with() | ||
|
||
def test_error_in_step2(self): | ||
# An initial request to an oauth_aware decorated path should | ||
# not redirect. | ||
|
@@ -855,10 +858,14 @@ def test_kwargs_are_passed_to_underlying_flow(self): | |
self.assertEqual(decorator.flow, decorator._tls.flow) | ||
|
||
def test_token_response_param(self): | ||
# No need to set-up a mock since test_required() does. | ||
self.decorator._token_response_param = 'foobar' | ||
self.test_required() | ||
|
||
def test_decorator_from_client_secrets(self): | ||
@mock.patch('oauth2client.transport.get_http_object') | ||
def test_decorator_from_client_secrets(self, new_http): | ||
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP) | ||
# Execute test after setting up mock. | ||
decorator = appengine.OAuth2DecoratorFromClientSecrets( | ||
datafile('client_secrets.json'), | ||
scope=['foo_scope', 'bar_scope']) | ||
|
@@ -877,6 +884,9 @@ def test_decorator_from_client_secrets(self): | |
self.assertEqual(self.decorator._revoke_uri, | ||
self.decorator.credentials.revoke_uri) | ||
|
||
# Check the mocks were called. | ||
new_http.assert_called_once_with() | ||
|
||
def test_decorator_from_client_secrets_toplevel(self): | ||
decorator_patch = mock.patch( | ||
'oauth2client.contrib.appengine.OAuth2DecoratorFromClientSecrets') | ||
|
@@ -915,7 +925,7 @@ def test_decorator_from_client_secrets_kwargs(self): | |
self.assertIn('prompt', decorator._kwargs) | ||
|
||
def test_decorator_from_cached_client_secrets(self): | ||
cache_mock = CacheMock() | ||
cache_mock = http_mock.CacheMock() | ||
load_and_cache('client_secrets.json', 'secret', cache_mock) | ||
decorator = appengine.OAuth2DecoratorFromClientSecrets( | ||
# filename, scope, message=None, cache=None | ||
|
@@ -991,7 +1001,10 @@ def test_decorator_from_client_secrets_with_optional_settings(self): | |
# This is never set, but it's consistent with other tests. | ||
self.assertFalse(decorator._in_error) | ||
|
||
def test_invalid_state(self): | ||
@mock.patch('oauth2client.transport.get_http_object') | ||
def test_invalid_state(self, new_http): | ||
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP) | ||
# Execute test after setting up mock. | ||
with mock.patch.object(appengine, '_parse_state_value', | ||
return_value=None, autospec=True): | ||
# Now simulate the callback to /oauth2callback. | ||
|
@@ -1002,6 +1015,9 @@ def test_invalid_state(self): | |
self.assertEqual('200 OK', response.status) | ||
self.assertEqual('The authorization request failed', response.body) | ||
|
||
# Check the mocks were called. | ||
new_http.assert_called_once_with() | ||
|
||
|
||
class DecoratorXsrfSecretTests(unittest2.TestCase): | ||
"""Test xsrf_secret_key.""" | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,6 @@ | |
import logging | ||
|
||
import flask | ||
import httplib2 | ||
import mock | ||
import six.moves.http_client as httplib | ||
import six.moves.urllib.parse as urlparse | ||
|
@@ -29,39 +28,20 @@ | |
from oauth2client import client | ||
from oauth2client import clientsecrets | ||
from oauth2client.contrib import flask_util | ||
from .. import http_mock | ||
|
||
|
||
__author__ = '[email protected] (Jon Wayne Parrott)' | ||
|
||
|
||
class Http2Mock(object): | ||
"""Mock httplib2.Http for code exchange / refresh""" | ||
|
||
def __init__(self, status=httplib.OK, **kwargs): | ||
self.status = status | ||
self.content = { | ||
'access_token': 'foo_access_token', | ||
'refresh_token': 'foo_refresh_token', | ||
'expires_in': 3600, | ||
'extra': 'value', | ||
} | ||
self.content.update(kwargs) | ||
|
||
def request(self, token_uri, method, body, headers, *args, **kwargs): | ||
self.body = body | ||
self.headers = headers | ||
return (self, json.dumps(self.content).encode('utf-8')) | ||
|
||
def __enter__(self): | ||
self.httplib2_orig = httplib2.Http | ||
httplib2.Http = self | ||
return self | ||
|
||
def __exit__(self, exc_type, exc_value, traceback): | ||
httplib2.Http = self.httplib2_orig | ||
|
||
def __call__(self, *args, **kwargs): | ||
return self | ||
DEFAULT_RESP = """\ | ||
{ | ||
"access_token": "foo_access_token", | ||
"expires_in": 3600, | ||
"extra": "value", | ||
"refresh_token": "foo_refresh_token" | ||
} | ||
""" | ||
|
||
|
||
class FlaskOAuth2Tests(unittest2.TestCase): | ||
|
@@ -246,7 +226,12 @@ def _setup_callback_state(self, client, **kwargs): | |
def test_callback_view(self): | ||
self.oauth2.storage = mock.Mock() | ||
with self.app.test_client() as client: | ||
with Http2Mock() as http: | ||
with mock.patch( | ||
'oauth2client.transport.get_http_object') as new_http: | ||
# Set-up mock. | ||
http = http_mock.HttpMock(data=DEFAULT_RESP) | ||
new_http.return_value = http | ||
# Run tests. | ||
state = self._setup_callback_state(client) | ||
|
||
response = client.get( | ||
|
@@ -258,6 +243,9 @@ def test_callback_view(self): | |
self.assertIn('codez', http.body) | ||
self.assertTrue(self.oauth2.storage.put.called) | ||
|
||
# Check the mocks were called. | ||
new_http.assert_called_once_with() | ||
|
||
def test_authorize_callback(self): | ||
self.oauth2.authorize_callback = mock.Mock() | ||
self.test_callback_view() | ||
|
@@ -296,11 +284,20 @@ def test_callback_view_errors(self): | |
with self.app.test_client() as client: | ||
state = self._setup_callback_state(client) | ||
|
||
with Http2Mock(status=httplib.INTERNAL_SERVER_ERROR): | ||
with mock.patch( | ||
'oauth2client.transport.get_http_object') as new_http: | ||
# Set-up mock. | ||
new_http.return_value = http_mock.HttpMock( | ||
headers={'status': httplib.INTERNAL_SERVER_ERROR}, | ||
data=DEFAULT_RESP) | ||
# Run tests. | ||
response = client.get( | ||
'/oauth2callback?state={0}&code=codez'.format(state)) | ||
self.assertEqual(response.status_code, httplib.BAD_REQUEST) | ||
|
||
# Check the mocks were called. | ||
new_http.assert_called_once_with() | ||
|
||
# Invalid state json | ||
with self.app.test_client() as client: | ||
with client.session_transaction() as session: | ||
|
@@ -495,7 +492,10 @@ def test_incremental_auth(self): | |
def test_incremental_auth_exchange(self): | ||
self._create_incremental_auth_app() | ||
|
||
with Http2Mock(): | ||
with mock.patch('oauth2client.transport.get_http_object') as new_http: | ||
# Set-up mock. | ||
new_http.return_value = http_mock.HttpMock(data=DEFAULT_RESP) | ||
# Run tests. | ||
with self.app.test_client() as client: | ||
state = self._setup_callback_state( | ||
client, | ||
|
@@ -511,16 +511,21 @@ def test_incremental_auth_exchange(self): | |
self.assertTrue( | ||
credentials.has_scopes(['email', 'one', 'two'])) | ||
|
||
# Check the mocks were called. | ||
new_http.assert_called_once_with() | ||
|
||
def test_refresh(self): | ||
token_val = 'new_token' | ||
json_resp = '{"access_token": "%s"}' % (token_val,) | ||
http = http_mock.HttpMock(data=json_resp) | ||
with self.app.test_request_context(): | ||
with mock.patch('flask.session'): | ||
self.oauth2.storage.put(self._generate_credentials()) | ||
|
||
self.oauth2.credentials.refresh( | ||
Http2Mock(access_token='new_token')) | ||
self.oauth2.credentials.refresh(http) | ||
|
||
self.assertEqual( | ||
self.oauth2.storage.get().access_token, 'new_token') | ||
self.oauth2.storage.get().access_token, token_val) | ||
|
||
def test_delete(self): | ||
with self.app.test_request_context(): | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,6 @@ | |
import datetime | ||
import json | ||
|
||
import httplib2 | ||
import mock | ||
from six.moves import http_client | ||
from tests.contrib.test_metadata import request_mock | ||
|
@@ -129,12 +128,12 @@ def test_retrieve_scopes(self, metadata): | |
service_account='default') | ||
|
||
@mock.patch('oauth2client.contrib._metadata.get_service_account_info', | ||
side_effect=httplib2.HttpLib2Error('No Such Email')) | ||
side_effect=http_client.HTTPException('No Such Email')) | ||
def test_retrieve_scopes_bad_email(self, metadata): | ||
http_request = mock.MagicMock() | ||
http_mock = mock.MagicMock(request=http_request) | ||
credentials = gce.AppAssertionCredentials(email='[email protected]') | ||
with self.assertRaises(httplib2.HttpLib2Error): | ||
with self.assertRaises(http_client.HTTPException): | ||
credentials.retrieve_scopes(http_mock) | ||
|
||
metadata.assert_called_once_with(http_request, | ||
|
Oops, something went wrong.