diff --git a/tests/test_appengine.py b/tests/test_appengine.py index 7261ee6..2e49a50 100644 --- a/tests/test_appengine.py +++ b/tests/test_appengine.py @@ -33,7 +33,7 @@ import urlparse import dev_appserver dev_appserver.fix_sys_path() -import mox +import mock import webapp2 from google.appengine.api import apiproxy_stub @@ -159,13 +159,9 @@ class TestAppAssertionCredentials(unittest.TestCase): 'memcache', memcache_stub.MemcacheServiceStub()) scope = 'http://www.googleapis.com/scope' - try: - credentials = AppAssertionCredentials(scope) - http = httplib2.Http() - credentials.refresh(http) - self.fail('Should have raised an AccessTokenRefreshError') - except AccessTokenRefreshError: - pass + credentials = AppAssertionCredentials(scope) + http = httplib2.Http() + self.assertRaises(AccessTokenRefreshError, credentials.refresh, http) def test_get_access_token_on_refresh(self): app_identity_stub = self.AppIdentityStubImpl() @@ -201,19 +197,19 @@ class TestAppAssertionCredentials(unittest.TestCase): def test_custom_service_account(self): scope = "http://www.googleapis.com/scope" account_id = "service_account_name_2@appspot.com" - m = mox.Mox() - m.StubOutWithMock(app_identity, 'get_access_token') - app_identity.get_access_token( - [scope], service_account_id=account_id).AndReturn(('a_token_456', None)) - m.ReplayAll() - credentials = AppAssertionCredentials(scope, service_account_id=account_id) - http = httplib2.Http() - credentials.refresh(http) - m.VerifyAll() - m.UnsetStubs() - self.assertEqual('a_token_456', credentials.access_token) - self.assertEqual(scope, credentials.scope) + with mock.patch.object(app_identity, 'get_access_token', + return_value=('a_token_456', None), + autospec=True) as get_access_token: + credentials = AppAssertionCredentials( + scope, service_account_id=account_id) + http = httplib2.Http() + credentials.refresh(http) + + self.assertEqual('a_token_456', credentials.access_token) + self.assertEqual(scope, credentials.scope) + get_access_token.assert_called_once_with( + [scope], service_account_id=account_id) def test_create_scoped_required_without_scopes(self): credentials = AppAssertionCredentials([]) @@ -538,7 +534,8 @@ class DecoratorTests(unittest.TestCase): 'wsgi.url_scheme': 'http', 'HTTP_HOST': 'localhost', }) - users.get_current_user = user_mock() + self.current_user = user_mock() + users.get_current_user = self.current_user self.httplib2_orig = httplib2.Http httplib2.Http = Http2Mock @@ -562,30 +559,28 @@ class DecoratorTests(unittest.TestCase): self.assertEqual('code', q['response_type'][0]) self.assertEqual(False, self.decorator.has_credentials()) - m = mox.Mox() - m.StubOutWithMock(appengine, '_parse_state_value') - appengine._parse_state_value('foo_path:xsrfkey123', - mox.IgnoreArg()).AndReturn('foo_path') - m.ReplayAll() + with mock.patch.object(appengine, '_parse_state_value', + return_value='foo_path', + autospec=True) as parse_state_value: + # Now simulate the callback to /oauth2callback. + response = self.app.get('/oauth2callback', { + 'code': 'foo_access_code', + 'state': 'foo_path:xsrfkey123', + }) + parts = response.headers['Location'].split('?', 1) + self.assertEqual('http://localhost/foo_path', parts[0]) + self.assertEqual(None, self.decorator.credentials) + if self.decorator._token_response_param: + response_query = urlparse.parse_qs(parts[1]) + response = response_query[self.decorator._token_response_param][0] + self.assertEqual(Http2Mock.content, + json.loads(urllib.unquote(response))) + self.assertEqual(self.decorator.flow, self.decorator._tls.flow) + self.assertEqual(self.decorator.credentials, + self.decorator._tls.credentials) - # Now simulate the callback to /oauth2callback. - response = self.app.get('/oauth2callback', { - 'code': 'foo_access_code', - 'state': 'foo_path:xsrfkey123', - }) - parts = response.headers['Location'].split('?', 1) - self.assertEqual('http://localhost/foo_path', parts[0]) - self.assertEqual(None, self.decorator.credentials) - if self.decorator._token_response_param: - response = urlparse.parse_qs( - parts[1])[self.decorator._token_response_param][0] - self.assertEqual(Http2Mock.content, json.loads(urllib.unquote(response))) - self.assertEqual(self.decorator.flow, self.decorator._tls.flow) - self.assertEqual(self.decorator.credentials, - self.decorator._tls.credentials) - - m.UnsetStubs() - m.VerifyAll() + parse_state_value.assert_called_once_with( + 'foo_path:xsrfkey123', self.current_user) # Now requesting the decorated path should work. response = self.app.get('/foo_path') @@ -599,13 +594,9 @@ class DecoratorTests(unittest.TestCase): # Raising an exception still clears the Credentials. self.should_raise = True - try: - response = self.app.get('/foo_path') - self.fail('Should have raised an exception.') - except Exception: - pass - self.assertEqual(None, self.decorator.credentials) + self.assertRaises(Exception, self.app.get, '/foo_path') self.should_raise = False + self.assertEqual(None, self.decorator.credentials) # Invalidate the stored Credentials. self.found_credentials.invalid = True @@ -623,37 +614,34 @@ class DecoratorTests(unittest.TestCase): response = self.app.get('/foo_path') self.assertTrue(response.status.startswith('302')) - m = mox.Mox() - m.StubOutWithMock(appengine, '_parse_state_value') - appengine._parse_state_value('foo_path:xsrfkey123', - mox.IgnoreArg()).AndReturn('foo_path') - m.ReplayAll() + with mock.patch.object(appengine, '_parse_state_value', + return_value='foo_path', + autospec=True) as parse_state_value: + # Now simulate the callback to /oauth2callback. + response = self.app.get('/oauth2callback', { + 'code': 'foo_access_code', + 'state': 'foo_path:xsrfkey123', + }) + self.assertEqual('http://localhost/foo_path', response.headers['Location']) + self.assertEqual(None, self.decorator.credentials) - # Now simulate the callback to /oauth2callback. - response = self.app.get('/oauth2callback', { - 'code': 'foo_access_code', - 'state': 'foo_path:xsrfkey123', - }) - self.assertEqual('http://localhost/foo_path', response.headers['Location']) - self.assertEqual(None, self.decorator.credentials) + # Now requesting the decorated path should work. + response = self.app.get('/foo_path') - # Now requesting the decorated path should work. - response = self.app.get('/foo_path') + self.assertTrue(self.had_credentials) - self.assertTrue(self.had_credentials) + # Credentials should be cleared after each call. + self.assertEqual(None, self.decorator.credentials) - # Credentials should be cleared after each call. - self.assertEqual(None, self.decorator.credentials) + # Invalidate the stored Credentials. + self.found_credentials.store.delete() - # Invalidate the stored Credentials. - self.found_credentials.store.delete() + # Invalid Credentials should start the OAuth dance again. + response = self.app.get('/foo_path') + self.assertTrue(response.status.startswith('302')) - # Invalid Credentials should start the OAuth dance again. - response = self.app.get('/foo_path') - self.assertTrue(response.status.startswith('302')) - - m.UnsetStubs() - m.VerifyAll() + parse_state_value.assert_called_once_with( + 'foo_path:xsrfkey123', self.current_user) def test_aware(self): # An initial request to an oauth_aware decorated path should not redirect. @@ -670,23 +658,20 @@ class DecoratorTests(unittest.TestCase): q['state'][0].rsplit(':', 1)[0]) self.assertEqual('code', q['response_type'][0]) - m = mox.Mox() - m.StubOutWithMock(appengine, '_parse_state_value') - appengine._parse_state_value('bar_path:xsrfkey456', - mox.IgnoreArg()).AndReturn('bar_path') - m.ReplayAll() + with mock.patch.object(appengine, '_parse_state_value', + return_value='bar_path', + autospec=True) as parse_state_value: + # Now simulate the callback to /oauth2callback. + url = self.decorator.authorize_url() + response = self.app.get('/oauth2callback', { + 'code': 'foo_access_code', + 'state': 'bar_path:xsrfkey456', + }) - # Now simulate the callback to /oauth2callback. - url = self.decorator.authorize_url() - response = self.app.get('/oauth2callback', { - 'code': 'foo_access_code', - 'state': 'bar_path:xsrfkey456', - }) - self.assertEqual('http://localhost/bar_path', response.headers['Location']) - self.assertEqual(False, self.decorator.has_credentials()) - - m.UnsetStubs() - m.VerifyAll() + self.assertEqual('http://localhost/bar_path', response.headers['Location']) + self.assertEqual(False, self.decorator.has_credentials()) + parse_state_value.assert_called_once_with( + 'bar_path:xsrfkey456', self.current_user) # Now requesting the decorated path will have credentials. response = self.app.get('/bar_path/2012/01') @@ -703,13 +688,9 @@ class DecoratorTests(unittest.TestCase): # Raising an exception still clears the Credentials. self.should_raise = True - try: - response = self.app.get('/bar_path/2012/01') - self.fail('Should have raised an exception.') - except Exception: - pass - self.assertEqual(None, self.decorator.credentials) + self.assertRaises(Exception, self.app.get, '/bar_path/2012/01') self.should_raise = False + self.assertEqual(None, self.decorator.credentials) def test_error_in_step2(self): diff --git a/tests/test_gce.py b/tests/test_gce.py index a700c81..ab0c154 100644 --- a/tests/test_gce.py +++ b/tests/test_gce.py @@ -20,13 +20,11 @@ Unit tests for oauth2client.gce. __author__ = 'jcgregorio@google.com (Joe Gregorio)' -import httplib2 -try: - from mox3 import mox -except ImportError: - import mox import unittest +import httplib2 +import mock + from oauth2client.client import AccessTokenRefreshError from oauth2client.client import Credentials from oauth2client.client import save_to_well_known_file @@ -36,56 +34,29 @@ from oauth2client.gce import AppAssertionCredentials class AssertionCredentialsTests(unittest.TestCase): def test_good_refresh(self): - m = mox.Mox() - - httplib2_response = m.CreateMock(object) - httplib2_response.status = 200 - - httplib2_request = m.CreateMock(object) - httplib2_request.__call__( - ('http://metadata.google.internal/0.1/meta-data/service-accounts/' - 'default/acquire' - '?scope=http%3A%2F%2Fexample.com%2Fa%20http%3A%2F%2Fexample.com%2Fb' - )).AndReturn((httplib2_response, '{"accessToken": "this-is-a-token"}')) - - m.ReplayAll() + http = mock.MagicMock() + http.request = mock.MagicMock( + return_value=(mock.Mock(status=200), + '{"accessToken": "this-is-a-token"}')) c = AppAssertionCredentials(scope=['http://example.com/a', 'http://example.com/b']) - - c._refresh(httplib2_request) - + self.assertEquals(None, c.access_token) + c.refresh(http) self.assertEquals('this-is-a-token', c.access_token) - m.UnsetStubs() - m.VerifyAll() + http.request.assert_called_exactly_once_with( + 'http://metadata.google.internal/0.1/meta-data/service-accounts/' + 'default/acquire' + '?scope=http%3A%2F%2Fexample.com%2Fa%20http%3A%2F%2Fexample.com%2Fb') def test_fail_refresh(self): - m = mox.Mox() - - httplib2_response = m.CreateMock(object) - httplib2_response.status = 400 - - httplib2_request = m.CreateMock(object) - httplib2_request.__call__( - ('http://metadata.google.internal/0.1/meta-data/service-accounts/' - 'default/acquire' - '?scope=http%3A%2F%2Fexample.com%2Fa%20http%3A%2F%2Fexample.com%2Fb' - )).AndReturn((httplib2_response, '{"accessToken": "this-is-a-token"}')) - - m.ReplayAll() + http = mock.MagicMock() + http.request = mock.MagicMock(return_value=(mock.Mock(status=400), '{}')) c = AppAssertionCredentials(scope=['http://example.com/a', 'http://example.com/b']) - - try: - c._refresh(httplib2_request) - self.fail('Should have raised exception on 400') - except AccessTokenRefreshError: - pass - - m.UnsetStubs() - m.VerifyAll() + self.assertRaises(AccessTokenRefreshError, c.refresh, http) def test_to_from_json(self): c = AppAssertionCredentials(scope=['http://example.com/a', @@ -111,30 +82,19 @@ class AssertionCredentialsTests(unittest.TestCase): self.assertEqual('dummy_scope', new_credentials.scope) def test_get_access_token(self): - m = mox.Mox() - - httplib2_response = m.CreateMock(object) - httplib2_response.status = 200 - - httplib2_request = m.CreateMock(object) - httplib2_request.__call__( - ('http://metadata.google.internal/0.1/meta-data/service-accounts/' - 'default/acquire?scope=dummy_scope' - )).AndReturn((httplib2_response, '{"accessToken": "this-is-a-token"}')) - - m.ReplayAll() + http = mock.MagicMock() + http.request = mock.MagicMock( + return_value=(mock.Mock(status=200), + '{"accessToken": "this-is-a-token"}')) credentials = AppAssertionCredentials(['dummy_scope']) - - http = httplib2.Http() - http.request = httplib2_request - token = credentials.get_access_token(http=http) self.assertEqual('this-is-a-token', token.access_token) self.assertEqual(None, token.expires_in) - m.UnsetStubs() - m.VerifyAll() + http.request.assert_called_exactly_once_with( + 'http://metadata.google.internal/0.1/meta-data/service-accounts/' + 'default/acquire?scope=dummy_scope') def test_save_to_well_known_file(self): credentials = AppAssertionCredentials([]) diff --git a/tests/test_keyring.py b/tests/test_keyring.py index 0c74516..ee6ba26 100644 --- a/tests/test_keyring.py +++ b/tests/test_keyring.py @@ -23,10 +23,8 @@ __author__ = 'jcgregorio@google.com (Joe Gregorio)' import datetime import keyring import unittest -try: - from mox3 import mox -except ImportError: - import mox + +import mock from oauth2client import GOOGLE_TOKEN_URI from oauth2client.client import OAuth2Credentials @@ -36,32 +34,22 @@ from oauth2client.keyring_storage import Storage class OAuth2ClientKeyringTests(unittest.TestCase): def test_non_existent_credentials_storage(self): - m = mox.Mox() - m.StubOutWithMock(keyring, 'get_password') - m.StubOutWithMock(keyring, 'set_password') - keyring.get_password('my_unit_test', 'me').AndReturn(None) - m.ReplayAll() - - s = Storage('my_unit_test', 'me') - credentials = s.get() - self.assertEquals(None, credentials) - - m.UnsetStubs() - m.VerifyAll() + with mock.patch.object(keyring, 'get_password', + return_value=None, + autospec=True) as get_password: + s = Storage('my_unit_test', 'me') + credentials = s.get() + self.assertEquals(None, credentials) + get_password.assert_called_once_with('my_unit_test', 'me') def test_malformed_credentials_in_storage(self): - m = mox.Mox() - m.StubOutWithMock(keyring, 'get_password') - m.StubOutWithMock(keyring, 'set_password') - keyring.get_password('my_unit_test', 'me').AndReturn('{') - m.ReplayAll() - - s = Storage('my_unit_test', 'me') - credentials = s.get() - self.assertEquals(None, credentials) - - m.UnsetStubs() - m.VerifyAll() + with mock.patch.object(keyring, 'get_password', + return_value='{', + autospec=True) as get_password: + s = Storage('my_unit_test', 'me') + credentials = s.get() + self.assertEquals(None, credentials) + get_password.assert_called_once_with('my_unit_test', 'me') def test_json_credentials_storage(self): access_token = 'foo' @@ -76,22 +64,28 @@ class OAuth2ClientKeyringTests(unittest.TestCase): refresh_token, token_expiry, GOOGLE_TOKEN_URI, user_agent) - m = mox.Mox() - m.StubOutWithMock(keyring, 'get_password') - m.StubOutWithMock(keyring, 'set_password') - keyring.get_password('my_unit_test', 'me').AndReturn(None) - keyring.set_password('my_unit_test', 'me', credentials.to_json()) - keyring.get_password('my_unit_test', 'me').AndReturn(credentials.to_json()) - m.ReplayAll() + # Setting autospec on a mock with an iterable side_effect is + # currently broken (http://bugs.python.org/issue17826), so instead + # we patch twice. + with mock.patch.object(keyring, 'get_password', + return_value=None, + autospec=True) as get_password: + with mock.patch.object(keyring, 'set_password', + return_value=None, + autospec=True) as set_password: + s = Storage('my_unit_test', 'me') + self.assertEquals(None, s.get()) - s = Storage('my_unit_test', 'me') - self.assertEquals(None, s.get()) + s.put(credentials) - s.put(credentials) + set_password.assert_called_once_with( + 'my_unit_test', 'me', credentials.to_json()) + get_password.assert_called_once_with('my_unit_test', 'me') - restored = s.get() - self.assertEqual('foo', restored.access_token) - self.assertEqual('some_client_id', restored.client_id) - - m.UnsetStubs() - m.VerifyAll() + with mock.patch.object(keyring, 'get_password', + return_value=credentials.to_json(), + autospec=True) as get_password: + restored = s.get() + self.assertEqual('foo', restored.access_token) + self.assertEqual('some_client_id', restored.client_id) + get_password.assert_called_once_with('my_unit_test', 'me') diff --git a/tests/test_oauth2client.py b/tests/test_oauth2client.py index 6b719c8..b961b08 100644 --- a/tests/test_oauth2client.py +++ b/tests/test_oauth2client.py @@ -206,16 +206,19 @@ class GoogleCredentialsTests(unittest.TestCase): def test_get_environment_gce_production(self): os.environ['SERVER_SOFTWARE'] = '' - with mock.patch.object(urllib.request, 'urlopen') as urlopen: - urlopen.return_value = MockResponse(['Metadata-Flavor: Google\r\n']) + response = MockResponse(['Metadata-Flavor: Google\r\n']) + with mock.patch.object(urllib.request, 'urlopen', + return_value=response, + autospec=True) as urlopen: self.assertEqual('GCE_PRODUCTION', _get_environment()) urlopen.assert_called_once_with( 'http://metadata.google.internal/', timeout=1) def test_get_environment_unknown(self): os.environ['SERVER_SOFTWARE'] = '' - with mock.patch.object(urllib.request, 'urlopen') as urlopen: - urlopen.return_value = MockResponse([]) + with mock.patch.object(urllib.request, 'urlopen', + return_value=MockResponse([]), + autospec=True) as urlopen: self.assertEqual(DEFAULT_ENV_NAME, _get_environment()) urlopen.assert_called_once_with( 'http://metadata.google.internal/', timeout=1) diff --git a/tox.ini b/tox.ini index d2ff4c5..45da06b 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,6 @@ envlist = py26,py27,py33,py34,pypy,cover [testenv] basedeps = keyring - mox3 mock pycrypto==2.6 django>=1.5,<1.6