Skip to content
This repository has been archived by the owner on Nov 5, 2019. It is now read-only.

Commit

Permalink
Merge pull request #585 from dhermes/remove-httplib2-from-unit-tests
Browse files Browse the repository at this point in the history
Removes usage of httplib2 in unit tests.
  • Loading branch information
dhermes authored Aug 3, 2016
2 parents c456547 + ed42b28 commit f04d521
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 235 deletions.
82 changes: 49 additions & 33 deletions tests/contrib/test_appengine.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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):
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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)

Expand All @@ -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)

Expand All @@ -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(
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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'])
Expand All @@ -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')
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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."""
Expand Down
75 changes: 40 additions & 35 deletions tests/contrib/test_flask_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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):
Expand Down Expand Up @@ -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(
Expand All @@ -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()
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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,
Expand All @@ -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():
Expand Down
5 changes: 2 additions & 3 deletions tests/contrib/test_gce.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
Loading

0 comments on commit f04d521

Please sign in to comment.