From 02b1a0522609e554f1748b72f20e531a269c1c3f Mon Sep 17 00:00:00 2001 From: Jamie Lennox <jamielennox@redhat.com> Date: Tue, 16 Dec 2014 15:36:40 +1000 Subject: [PATCH] Replace mox in tests with requests-mock requests-mock is a tool specifically designed for mocking responses from the requests library. Use that instead of handling mox and mock ourselves. Change-Id: Ifd855b8d6c1b401e29ac210593c48d2da87a571b --- test-requirements.txt | 3 +- tests/test_http.py | 179 +++++++++++++----------------------------- 2 files changed, 57 insertions(+), 125 deletions(-) diff --git a/test-requirements.txt b/test-requirements.txt index 06cb4aaa..ce8fc670 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,9 +5,10 @@ hacking>=0.8.0,<0.9 coverage>=3.6 discover -mox3>=0.7.0 mock>=1.0 oslosphinx>=2.2.0 # Apache-2.0 sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3 testrepository>=0.0.18 testtools>=0.9.36,!=1.2.0 +fixtures>=0.3.14 +requests-mock>=0.6.0 # Apache-2.0 diff --git a/tests/test_http.py b/tests/test_http.py index daab8057..f9a5a237 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -14,9 +14,8 @@ # under the License. import json -import mock -from mox3 import mox import requests +from requests_mock.contrib import fixture import six from six.moves.urllib import parse import testtools @@ -33,16 +32,11 @@ class TestClient(testtools.TestCase): def setUp(self): super(TestClient, self).setUp() - self.mock = mox.Mox() - self.mock.StubOutWithMock(requests.Session, 'request') + self.mock = self.useFixture(fixture.Fixture()) self.endpoint = 'http://example.com:9292' self.client = http.HTTPClient(self.endpoint, token=u'abc123') - def tearDown(self): - super(TestClient, self).tearDown() - self.mock.UnsetStubs() - def test_identity_headers_and_token(self): identity_headers = { 'X-Auth-Token': 'auth_token', @@ -97,25 +91,22 @@ class TestClient(testtools.TestCase): # when creating the http client, the session headers don't contain # the X-Auth-Token key. identity_headers = { - b'X-User-Id': b'user', - b'X-Tenant-Id': b'tenant', - b'X-Roles': b'roles', - b'X-Identity-Status': b'Confirmed', - b'X-Service-Catalog': b'service_catalog', + 'X-User-Id': b'user', + 'X-Tenant-Id': b'tenant', + 'X-Roles': b'roles', + 'X-Identity-Status': b'Confirmed', + 'X-Service-Catalog': b'service_catalog', } kwargs = {'identity_headers': identity_headers} http_client = http.HTTPClient(self.endpoint, **kwargs) - def check_headers(*args, **kwargs): - headers = kwargs.get('headers') - for k, v in six.iteritems(identity_headers): - self.assertEqual(v, headers[k]) + path = '/v1/images/my-image' + self.mock.get(self.endpoint + path) + http_client.get(path) - return utils.FakeResponse({}, six.StringIO('{}')) - - with mock.patch.object(http_client.session, 'request') as mreq: - mreq.side_effect = check_headers - http_client.get('http://example.com:9292/v1/images/my-image') + headers = self.mock.last_request.headers + for k, v in six.iteritems(identity_headers): + self.assertEqual(v, headers[k]) def test_connection_refused(self): """ @@ -123,43 +114,27 @@ class TestClient(testtools.TestCase): And the error should list the host and port that refused the connection """ - requests.Session.request( - mox.IgnoreArg(), - mox.IgnoreArg(), - data=mox.IgnoreArg(), - headers=mox.IgnoreArg(), - stream=mox.IgnoreArg(), - ).AndRaise(requests.exceptions.ConnectionError()) - self.mock.ReplayAll() - try: - self.client.get('/v1/images/detail?limit=20') - #NOTE(alaski) We expect exc.CommunicationError to be raised - # so we should never reach this point. try/except is used here - # rather than assertRaises() so that we can check the body of - # the exception. - self.fail('An exception should have bypassed this line.') - except glanceclient.exc.CommunicationError as comm_err: - fail_msg = ("Exception message '%s' should contain '%s'" % - (comm_err.message, self.endpoint)) - self.assertTrue(self.endpoint in comm_err.message, fail_msg) + def cb(request, context): + raise requests.exceptions.ConnectionError() + + path = '/v1/images/detail?limit=20' + self.mock.get(self.endpoint + path, text=cb) + + comm_err = self.assertRaises(glanceclient.exc.CommunicationError, + self.client.get, + '/v1/images/detail?limit=20') + + self.assertIn(self.endpoint, comm_err.message) def test_http_encoding(self): - # Lets fake the response - # returned by requests - response = 'Ok' - headers = {"Content-Type": "text/plain"} - fake = utils.FakeResponse(headers, six.StringIO(response)) - requests.Session.request( - mox.IgnoreArg(), - mox.IgnoreArg(), - data=mox.IgnoreArg(), - stream=mox.IgnoreArg(), - headers=mox.IgnoreArg()).AndReturn(fake) - self.mock.ReplayAll() + path = '/v1/images/detail' + text = 'Ok' + self.mock.get(self.endpoint + path, text=text, + headers={"Content-Type": "text/plain"}) headers = {"test": u'ni\xf1o'} - resp, body = self.client.get('/v1/images/detail', headers=headers) - self.assertEqual(fake, resp) + resp, body = self.client.get(path, headers=headers) + self.assertEqual(text, resp.text) def test_headers_encoding(self): value = u'ni\xf1o' @@ -171,18 +146,14 @@ class TestClient(testtools.TestCase): def test_raw_request(self): " Verify the path being used for HTTP requests reflects accurately. " headers = {"Content-Type": "text/plain"} - response = 'Ok' - fake = utils.FakeResponse({}, six.StringIO(response)) - requests.Session.request( - mox.IgnoreArg(), - mox.IgnoreArg(), - data=mox.IgnoreArg(), - stream=mox.IgnoreArg(), - headers=mox.IgnoreArg()).AndReturn(fake) - self.mock.ReplayAll() + text = 'Ok' + path = '/v1/images/detail' + + self.mock.get(self.endpoint + path, text=text, headers=headers) resp, body = self.client.get('/v1/images/detail', headers=headers) - self.assertEqual(fake, resp) + self.assertEqual(headers, resp.headers) + self.assertEqual(text, resp.text) def test_parse_endpoint(self): endpoint = 'http://example.com:9292' @@ -199,76 +170,36 @@ class TestClient(testtools.TestCase): self.assertEqual(test_client.timeout, 600.0) def test_http_chunked_request(self): - # Lets fake the response - # returned by requests - response = "Ok" - data = six.StringIO(response) - fake = utils.FakeResponse({}, data) - requests.Session.request( - mox.IgnoreArg(), - mox.IgnoreArg(), - stream=mox.IgnoreArg(), - data=mox.IsA(types.GeneratorType), - headers=mox.IgnoreArg()).AndReturn(fake) - self.mock.ReplayAll() + text = "Ok" + data = six.StringIO(text) + path = '/v1/images/' + self.mock.post(self.endpoint + path, text=text) headers = {"test": u'chunked_request'} - resp, body = self.client.post('/v1/images/', - headers=headers, data=data) - self.assertEqual(fake, resp) + resp, body = self.client.post(path, headers=headers, data=data) + self.assertIsInstance(self.mock.last_request.body, types.GeneratorType) + self.assertEqual(text, resp.text) def test_http_json(self): data = {"test": "json_request"} - fake = utils.FakeResponse({}, b"OK") - - def test_json(passed_data): - """ - This function tests whether the data - being passed to request's method is - a valid json or not. - - This function will be called by pymox - - :params passed_data: The data being - passed to requests.Session.request. - """ - if not isinstance(passed_data, six.string_types): - return False - - try: - passed_data = json.loads(passed_data) - return data == passed_data - except (TypeError, ValueError): - return False - - requests.Session.request( - mox.IgnoreArg(), - mox.IgnoreArg(), - stream=mox.IgnoreArg(), - data=mox.Func(test_json), - headers=mox.IgnoreArg()).AndReturn(fake) - self.mock.ReplayAll() + path = '/v1/images' + text = 'OK' + self.mock.post(self.endpoint + path, text=text) headers = {"test": u'chunked_request'} - resp, body = self.client.post('/v1/images/', - headers=headers, - data=data) - self.assertEqual(fake, resp) + resp, body = self.client.post(path, headers=headers, data=data) + + self.assertEqual(text, resp.text) + self.assertIsInstance(self.mock.last_request.body, six.string_types) + self.assertEqual(data, json.loads(self.mock.last_request.body)) def test_http_chunked_response(self): - headers = {"Content-Type": "application/octet-stream"} data = "TEST" - fake = utils.FakeResponse(headers, six.StringIO(data)) + path = '/v1/images/' + self.mock.get(self.endpoint + path, body=six.StringIO(data), + headers={"Content-Type": "application/octet-stream"}) - requests.Session.request( - mox.IgnoreArg(), - mox.IgnoreArg(), - stream=mox.IgnoreArg(), - data=mox.IgnoreArg(), - headers=mox.IgnoreArg()).AndReturn(fake) - self.mock.ReplayAll() - headers = {"test": u'chunked_request'} - resp, body = self.client.get('/v1/images/') + resp, body = self.client.get(path) self.assertTrue(isinstance(body, types.GeneratorType)) self.assertEqual([data], list(body))