Remove httpretty from resource tests

The major change here is that httpretty is removed from test_resource in
favor of using a Mock session based off of the Session class.

Common replacements were:
* stub_url usage was replaced with a Mock return_value on the verb that
  was being stubbed.
* Places where we were accessing httpretty.last_request use some form of
  call_args on session verbs. Additionally, for the common case of
  checking whether an expected URL was generated to be called,
  assertCalledURL was created on the ResourceTests class.
* Some minor rearrangements to move several test methods out of TestFind
  and back into ResourceTests where they belong.

Change-Id: I743dc31965b7f2329f5d5ad80fea09e0da0cba73
This commit is contained in:
Brian Curtin
2015-03-16 14:40:13 -05:00
parent a90cd6e5a4
commit 2ae87643e8

View File

@@ -10,10 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import json
import os
import httpretty
import mock
import requests
from testtools import matchers
@@ -24,7 +23,6 @@ from openstack import resource
from openstack import session
from openstack.tests import base
from openstack.tests import fakes
from openstack import transport
from openstack import utils
fake_name = 'rey'
@@ -238,13 +236,16 @@ class ResourceTests(base.TestTransportBase):
def setUp(self):
super(ResourceTests, self).setUp()
self.transport = transport.Transport(accept=transport.JSON)
self.auth = fakes.FakeAuthenticator()
self.session = session.Session(self.transport, self.auth)
self.session = mock.Mock(spec=session.Session)
def assertCalledURL(self, method, url):
# call_args gives a tuple of *args and tuple of **kwargs.
# Check that the first arg in *args (the URL) has our url.
self.assertEqual(method.call_args[0][0], url)
@httpretty.activate
def test_empty_id(self):
self.stub_url(httpretty.GET, path=[fake_path], json=fake_body)
self.session.get.return_value = mock.Mock(body=fake_body)
obj = FakeResource.new(**fake_arguments)
self.assertEqual(obj, obj.get(self.session))
@@ -437,6 +438,7 @@ class ResourceTests(base.TestTransportBase):
attrs, json_body):
class FakeResource2(FakeResource):
put_update = False
resource_key = key
service = "my_service"
@@ -504,9 +506,9 @@ class ResourceTests(base.TestTransportBase):
service=FakeResource2.service,
accept=None)
@httpretty.activate
def test_create(self):
self.stub_url(httpretty.POST, path=fake_path, json=fake_body)
resp = mock.Mock(body=fake_body)
self.session.post = mock.Mock(return_value=resp)
obj = FakeResource.new(name=fake_name,
enabled=True,
@@ -516,7 +518,8 @@ class ResourceTests(base.TestTransportBase):
self.assertEqual(obj, obj.create(self.session))
self.assertFalse(obj.is_dirty)
last_req = httpretty.last_request().parsed_body[fake_resource]
last_req = self.session.post.call_args[1]["json"][
FakeResource.resource_key]
self.assertEqual(4, len(last_req))
self.assertEqual('True', last_req['enabled'])
@@ -535,12 +538,18 @@ class ResourceTests(base.TestTransportBase):
self.assertEqual(fake_attr1, obj.first)
self.assertEqual(fake_attr2, obj.second)
@httpretty.activate
def test_get(self):
self.stub_url(httpretty.GET, path=[fake_path, fake_id], json=fake_body)
resp = mock.Mock(body=fake_body)
self.session.get = mock.Mock(return_value=resp)
obj = FakeResource.get_by_id(self.session, fake_id,
path_args=fake_arguments)
# Check that the proper URL is being built.
self.assertCalledURL(self.session.get,
os.path.join(fake_base_path % fake_arguments,
str(fake_id))[1:])
self.assertEqual(fake_id, obj.id)
self.assertEqual(fake_name, obj['name'])
self.assertEqual(fake_attr1, obj['attr1'])
@@ -550,14 +559,14 @@ class ResourceTests(base.TestTransportBase):
self.assertEqual(fake_attr1, obj.first)
self.assertEqual(fake_attr2, obj.second)
@httpretty.activate
def test_get_with_headers(self):
header1 = "fake-value1"
header2 = "fake-value2"
headers = {"header1": header1,
"header2": header2}
self.stub_url(httpretty.GET, path=[fake_path, fake_id], json=fake_body,
**headers)
resp = mock.Mock(body=fake_body, headers=headers)
self.session.get = mock.Mock(return_value=resp)
class FakeResource2(FakeResource):
header1 = resource.header("header1")
@@ -567,6 +576,10 @@ class ResourceTests(base.TestTransportBase):
path_args=fake_arguments,
include_headers=True)
self.assertCalledURL(self.session.get,
os.path.join(fake_base_path % fake_arguments,
str(fake_id))[1:])
self.assertEqual(fake_id, obj.id)
self.assertEqual(fake_name, obj['name'])
self.assertEqual(fake_attr1, obj['attr1'])
@@ -580,83 +593,88 @@ class ResourceTests(base.TestTransportBase):
self.assertEqual(header1, obj.header1)
self.assertEqual(header2, obj.header2)
@httpretty.activate
def test_head(self):
class FakeResource2(FakeResource):
header1 = resource.header("header1")
header2 = resource.header("header2")
self.stub_url(httpretty.HEAD, path=[fake_path, fake_id],
header1='one',
header2='two')
resp = mock.Mock(headers={"header1": "one", "header2": "two"})
self.session.head = mock.Mock(return_value=resp)
obj = FakeResource2.head_by_id(self.session, fake_id,
path_args=fake_arguments)
self.assertCalledURL(self.session.head,
os.path.join(fake_base_path % fake_arguments,
str(fake_id))[1:])
self.assertEqual('one', obj['headers']['header1'])
self.assertEqual('two', obj['headers']['header2'])
self.assertEqual('one', obj.header1)
self.assertEqual('two', obj.header2)
@httpretty.activate
def test_update(self):
FakeResource.put_update = False
new_attr1 = 'attr5'
new_attr2 = 'attr6'
fake_body1 = copy.deepcopy(fake_body)
fake_body1[fake_resource]['attr1'] = new_attr1
def test_patch_update(self):
class FakeResourcePatch(FakeResource):
put_update = False
self.stub_url(httpretty.POST, path=fake_path, json=fake_body1)
self.stub_url(httpretty.PATCH,
path=[fake_path, fake_id],
json=fake_body)
resp = mock.Mock(body=fake_body)
self.session.patch = mock.Mock(return_value=resp)
obj = FakeResource.new(name=fake_name,
attr1=new_attr1,
attr2=new_attr2)
self.assertEqual(obj, obj.create(self.session))
self.assertFalse(obj.is_dirty)
self.assertEqual(new_attr1, obj['attr1'])
obj['attr1'] = fake_attr1
obj.second = fake_attr2
obj = FakeResourcePatch.new(id=fake_id, name=fake_name,
attr1=fake_attr1, attr2=fake_attr2)
self.assertTrue(obj.is_dirty)
self.assertEqual(obj, obj.update(self.session))
self.assertFalse(obj.is_dirty)
last_req = httpretty.last_request().parsed_body[fake_resource]
self.assertEqual(2, len(last_req))
self.assertCalledURL(self.session.patch,
os.path.join(fake_base_path % fake_arguments,
str(fake_id))[1:])
last_req = self.session.patch.call_args[1]["json"][
FakeResource.resource_key]
self.assertEqual(3, len(last_req))
self.assertEqual(fake_name, last_req['name'])
self.assertEqual(fake_attr1, last_req['attr1'])
self.assertEqual(fake_attr2, last_req['attr2'])
self.assertEqual(fake_id, obj.id)
self.assertEqual(fake_name, obj['name'])
self.assertEqual(fake_attr1, obj['attr1'])
self.assertEqual(fake_attr2, obj['attr2'])
self.assertEqual(fake_name, obj.name)
self.assertEqual(fake_attr1, obj.first)
self.assertEqual(fake_attr2, obj.second)
obj = FakeResource.new(id=fake_id,
name=fake_name,
attr1=new_attr1,
attr2=new_attr2)
put_data = {'id': fake_id}
put_body = {fake_resource: put_data}
self.stub_url(httpretty.PUT,
path=[fake_path, fake_id],
json=put_body)
FakeResource.put_update = True
def test_put_update(self):
class FakeResourcePut(FakeResource):
put_update = True
resp = mock.Mock(body=fake_body)
self.session.put = mock.Mock(return_value=resp)
obj = FakeResourcePut.new(id=fake_id, name=fake_name,
attr1=fake_attr1, attr2=fake_attr2)
self.assertTrue(obj.is_dirty)
self.assertEqual(obj, obj.update(self.session))
FakeResource.put_update = False
last_req = httpretty.last_request()
self.assertEqual('PUT', last_req.command)
last_data = last_req.parsed_body[fake_resource]
self.assertEqual(3, len(last_data))
self.assertEqual(new_attr2, last_data['attr2'])
self.assertEqual(new_attr1, last_data['attr1'])
self.assertEqual(fake_name, last_data['name'])
self.assertFalse(obj.is_dirty)
self.assertCalledURL(self.session.put,
os.path.join(fake_base_path % fake_arguments,
str(fake_id))[1:])
last_req = self.session.put.call_args[1]["json"][
FakeResource.resource_key]
self.assertEqual(3, len(last_req))
self.assertEqual(fake_name, last_req['name'])
self.assertEqual(fake_attr1, last_req['attr1'])
self.assertEqual(fake_attr2, last_req['attr2'])
self.assertEqual(fake_id, obj.id)
self.assertEqual(fake_name, obj.name)
self.assertEqual(fake_attr1, obj.first)
self.assertEqual(fake_attr2, obj.second)
def test_update_early_exit(self):
obj = FakeResource()
@@ -672,39 +690,37 @@ class ResourceTests(base.TestTransportBase):
# we handle the resulting KeyError.
self.assertEqual(obj, obj.update("session"))
@httpretty.activate
def test_delete(self):
self.stub_url(httpretty.GET, path=[fake_path, fake_id], json=fake_body)
self.stub_url(httpretty.DELETE, [fake_path, fake_id])
obj = FakeResource.get_by_id(self.session, fake_id,
path_args=fake_arguments)
obj = FakeResource({"id": fake_id, "name": fake_name})
obj.delete(self.session)
last_req = httpretty.last_request()
self.assertEqual('DELETE', last_req.method)
self.assertEqual('/endpoint/fakes/rey/data/99', last_req.path)
self.assertCalledURL(self.session.delete,
os.path.join(fake_base_path % fake_arguments,
str(fake_id))[1:])
@httpretty.activate
def _test_list(self, json_sentinel, json_body, resource_class):
def _test_list(self, resource_class):
results = [fake_data.copy(), fake_data.copy(), fake_data.copy()]
for i in range(len(results)):
results[i]['id'] = fake_id + i
if resource_class.resources_key is not None:
body = {resource_class.resources_key:
self._get_expected_results()}
sentinel = {resource_class.resources_key: []}
else:
body = self._get_expected_results()
sentinel = []
marker = "marker=%d" % results[-1]['id']
self.stub_url(httpretty.GET,
path=[fake_path + "?" + marker],
json=json_sentinel,
match_querystring=True)
self.stub_url(httpretty.GET,
path=[fake_path],
json=json_body)
self.session.get.side_effect = [mock.Mock(body=body),
mock.Mock(body=sentinel)]
objs = resource_class.list(self.session, limit=1,
path_args=fake_arguments,
paginated=True)
objs = list(objs)
self.assertIn(marker, httpretty.last_request().path)
self.assertIn(marker, self.session.get.call_args[0][0])
self.assertEqual(3, len(objs))
for obj in objs:
@@ -713,6 +729,18 @@ class ResourceTests(base.TestTransportBase):
self.assertEqual(fake_name, obj.name)
self.assertIsInstance(obj, FakeResource)
def _get_expected_results(self):
results = [fake_data.copy(), fake_data.copy(), fake_data.copy()]
for i in range(len(results)):
results[i]['id'] = fake_id + i
return results
def test_list_keyed_resource(self):
self._test_list(FakeResource)
def test_list_non_keyed_resource(self):
self._test_list(FakeResourceNoKeys)
def _test_list_call_count(self, paginated):
# Test that we've only made one call to receive all data
results = [fake_data.copy(), fake_data.copy(), fake_data.copy()]
@@ -766,26 +794,6 @@ class ResourceTests(base.TestTransportBase):
path = fake_base_path
session.get.assert_called_with(path, params={}, service=None)
def _get_expected_results(self):
results = [fake_data.copy(), fake_data.copy(), fake_data.copy()]
for i in range(len(results)):
results[i]['id'] = fake_id + i
return results
@httpretty.activate
def test_list_keyed_resource(self):
sentinel = {fake_resources: []}
body = {fake_resources: self._get_expected_results()}
cls = FakeResource
self._test_list(sentinel, body, cls)
@httpretty.activate
def test_list_non_keyed_resource(self):
sentinel = []
body = self._get_expected_results()
cls = FakeResourceNoKeys
self._test_list(sentinel, body, cls)
def test_attrs(self):
obj = FakeResource()
@@ -898,6 +906,74 @@ class ResourceTests(base.TestTransportBase):
self.assertEqual(ID, resource.Resource.get_id(ID))
self.assertEqual(ID, resource.Resource.get_id(res))
def test_repr(self):
fr = FakeResource()
fr._loaded = False
fr.first = "hey"
fr.second = "hi"
fr.third = "nah"
the_repr = repr(fr)
result = eval(the_repr)
self.assertEqual(fr._loaded, result._loaded)
self.assertEqual(fr.first, result.first)
self.assertEqual(fr.second, result.second)
self.assertEqual(fr.third, result.third)
def test_id_attribute(self):
faker = FakeResource(fake_data)
self.assertEqual(fake_id, faker.id)
faker.id_attribute = 'name'
self.assertEqual(fake_name, faker.id)
faker.id_attribute = 'attr1'
self.assertEqual(fake_attr1, faker.id)
faker.id_attribute = 'attr2'
self.assertEqual(fake_attr2, faker.id)
faker.id_attribute = 'id'
self.assertEqual(fake_id, faker.id)
def test_name_attribute(self):
class Person_ES(resource.Resource):
name_attribute = "nombre"
nombre = resource.prop('nombre')
name = "Brian"
args = {'nombre': name}
person = Person_ES(args)
self.assertEqual(name, person.nombre)
self.assertEqual(name, person.name)
new_name = "Julien"
person.name = new_name
self.assertEqual(new_name, person.nombre)
self.assertEqual(new_name, person.name)
def test_boolstr_prop(self):
faker = FakeResource(fake_data)
self.assertEqual(True, faker.enabled)
self.assertEqual('True', faker['enabled'])
faker.enabled = False
self.assertEqual(False, faker.enabled)
self.assertEqual('False', faker['enabled'])
# should fail fast
def set_invalid():
faker.enabled = 'INVALID'
self.assertRaises(ValueError, set_invalid)
@mock.patch("openstack.resource.Resource.list")
def test_fallthrough(self, mock_list):
class FakeResource2(FakeResource):
name_attribute = None
@classmethod
def page(cls, session, limit=None, marker=None, path_args=None,
**params):
raise exceptions.HttpException("exception")
self.assertEqual(None, FakeResource2.find("session", "123"))
class ResourceMapping(base.TestCase):
@@ -1118,71 +1194,3 @@ class TestFind(base.TestCase):
FakeResource.name_attribute = None
self.assertEqual(None, FakeResource.find(self.mock_session, self.NAME))
def test_repr(self):
fr = FakeResource()
fr._loaded = False
fr.first = "hey"
fr.second = "hi"
fr.third = "nah"
the_repr = repr(fr)
result = eval(the_repr)
self.assertEqual(fr._loaded, result._loaded)
self.assertEqual(fr.first, result.first)
self.assertEqual(fr.second, result.second)
self.assertEqual(fr.third, result.third)
def test_id_attribute(self):
faker = FakeResource(fake_data)
self.assertEqual(fake_id, faker.id)
faker.id_attribute = 'name'
self.assertEqual(fake_name, faker.id)
faker.id_attribute = 'attr1'
self.assertEqual(fake_attr1, faker.id)
faker.id_attribute = 'attr2'
self.assertEqual(fake_attr2, faker.id)
faker.id_attribute = 'id'
self.assertEqual(fake_id, faker.id)
def test_name_attribute(self):
class Person_ES(resource.Resource):
name_attribute = "nombre"
nombre = resource.prop('nombre')
name = "Brian"
args = {'nombre': name}
person = Person_ES(args)
self.assertEqual(name, person.nombre)
self.assertEqual(name, person.name)
new_name = "Julien"
person.name = new_name
self.assertEqual(new_name, person.nombre)
self.assertEqual(new_name, person.name)
def test_boolstr_prop(self):
faker = FakeResource(fake_data)
self.assertEqual(True, faker.enabled)
self.assertEqual('True', faker['enabled'])
faker.enabled = False
self.assertEqual(False, faker.enabled)
self.assertEqual('False', faker['enabled'])
# should fail fast
def set_invalid():
faker.enabled = 'INVALID'
self.assertRaises(ValueError, set_invalid)
@mock.patch("openstack.resource.Resource.list")
def test_fallthrough(self, mock_list):
class FakeResource2(FakeResource):
name_attribute = None
@classmethod
def page(cls, session, limit=None, marker=None, path_args=None,
**params):
raise exceptions.HttpException("exception")
self.assertEqual(None, FakeResource2.find("session", "123"))