diff --git a/nailgun/entity_mixins.py b/nailgun/entity_mixins.py index 7c290b2c..398ea75a 100644 --- a/nailgun/entity_mixins.py +++ b/nailgun/entity_mixins.py @@ -11,6 +11,7 @@ from fauxfactory import gen_choice from inflection import pluralize +from requests.exceptions import HTTPError, JSONDecodeError from nailgun import client, config from nailgun.entity_fields import IntegerField, ListField, OneToManyField, OneToOneField @@ -947,7 +948,12 @@ def create_json(self, create_missing=None): """ response = self.create_raw(create_missing) - response.raise_for_status() + try: + response.raise_for_status() + except HTTPError as e: + with contextlib.suppress(JSONDecodeError): + e.args += (response.json(),) + raise e return response.json() def create(self, create_missing=None): diff --git a/tests/test_entity_mixins.py b/tests/test_entity_mixins.py index ba46b8db..d6c069ce 100644 --- a/tests/test_entity_mixins.py +++ b/tests/test_entity_mixins.py @@ -3,7 +3,7 @@ from unittest import TestCase, mock from fauxfactory import gen_integer -from requests.exceptions import HTTPError +from requests.exceptions import HTTPError, JSONDecodeError from nailgun import client, config, entity_mixins from nailgun.entity_fields import ( @@ -621,6 +621,27 @@ def test_create_json(self): self.assertEqual(response.raise_for_status.call_count, 1) self.assertEqual(response.json.call_count, 1) + def test_create_json_with_exception(self): + """Check what happens if the server returns an error HTTP status code for :meth:`nailgun.entity_mixins.EntityCreateMixin.create_json`.""" + for valid_json in (True, False): + response = mock.Mock() + return_value = {"a": "b"} + response.raise_for_status.side_effect = HTTPError("foo") + if valid_json: + response.json.return_value = return_value + else: + response.json.side_effect = JSONDecodeError("msg", "foo", 2) + with mock.patch.object( + self.entity, 'create_raw', return_value=response + ), self.assertRaises(HTTPError) as error: + self.entity.create_json() + self.assertEqual(response.raise_for_status.call_count, 1) + self.assertEqual(response.json.call_count, 1) + if valid_json: + self.assertEqual(error.exception.args[1], return_value) + else: + self.assertEqual(len(error.exception.args), 1) + def test_create(self): """Test :meth:`nailgun.entity_mixins.EntityCreateMixin.create`."""