def test_register_resource_duplicate_url(self): '''This test case ensures different resources can not be registered under the same name.''' resource1 = Resource(name="app-setting", url="/app-settings") resource2 = Resource(name="custom-setting", url="/app-settings") self._register_resource_duplicate(resource1, resource2)
def setup_once(cls): '''This method is invoked once for setting up common dependencies for all test cases.''' FantasticoUnitTestsCase.setup_once() InvoiceMock.get_required_scopes = lambda inst = None: None resource = Resource(name="Invoice", url="/invoices", subresources={"items": []}) resource._model = InvoiceMock cls.resource_ref = resource
def setup_once(cls): '''This method is invoked once for setting up common dependencies for all test cases.''' FantasticoUnitTestsCase.setup_once() InvoiceMock.get_required_scopes = lambda inst=None: None resource = Resource(name="Invoice", url="/invoices", subresources={"items": []}) resource._model = InvoiceMock cls.resource_ref = resource
def test_update_item_resource_invalid(self): '''This test case ensures an item is not updated if it fails validation.''' expected_body = {} url = "/simple-resources" version = "1.0" resource = Resource(name="Mock Simple Resource", url=url, version=float(version), validator=MockSimpleResourceValidator) resource(MockSimpleResourceRoa, self._resources_registry) resource_id = 1986 request = Mock() request.body = json.dumps(expected_body).encode() self._resources_registry.find_by_url = Mock(return_value=resource) self._json_serializer.deserialize = Mock( return_value=MockSimpleResourceRoa()) response = self._controller.update_item(request, version, url, resource_id) self._assert_resource_error(response, 400, 10010, version, url) self._resources_registry.find_by_url.assert_called_once_with( url, float(version)) self._json_serializer.deserialize.assert_called_once_with( json.dumps(expected_body))
def test_get_item_inexistent_resource(self): '''This test case covers the scenario for retrieving an inexisten item from an existing collection.''' url = "/simple-resources" version = "1.0" resource = Resource(name="Mock Simple Resource", url=url, version=float(version)) resource(MockSimpleResourceRoa, self._resources_registry) resource_id = 1986 self._resources_registry.find_by_url = Mock(return_value=resource) self._model_facade.model_pk_cols = [MockSimpleResourceRoa.id] self._model_facade.find_by_pk = Mock(return_value=None) response = self._controller.get_item(Mock(), version, url, resource_id) self._assert_resource_error(response, 404, 10040, version, url) self.assertTrue( resource_id, json.loads(response.body.decode())["error_description"]) self._resources_registry.find_by_url.assert_called_once_with( url, float(version)) self._model_facade.find_by_pk.assert_called_once_with( {MockSimpleResourceRoa.id: resource_id})
def test_register_resource_duplicate_nameversion(self): '''This test case ensures an exception is raised when we try to register multiple resources with the same name and version.''' resource = Resource(name="app-setting", url="/app-settings") self._register_resource_duplicate(resource, resource)
def test_create_item_dbexception(self): '''This test case ensures an error response is received if an unexpected db error occurs when creating the resource.''' resource = Resource(name="Mock Simple Resource", url="/mock-simple-resources", version=1.0) resource(MockSimpleResourceRoa, self._resources_registry) request_body = { "name": "simple-resource1", "description": "Simple resource description." } expected_model = MockSimpleResourceRoa( name=request_body.get("name"), description=request_body.get("description")) request = Mock() request.body = json.dumps(request_body).encode() self._resources_registry.find_by_url = Mock(return_value=resource) self._json_serializer.deserialize = Mock(return_value=expected_model) self._model_facade.create = Mock( side_effect=FantasticoDbError("Unexpected db error.")) response = self._controller.create_item_latest(request, resource.url) self._assert_resource_error(response, 400, 10030, str(resource.version), resource.url) self._resources_registry.find_by_url.assert_called_once_with( resource.url, "latest") self._json_serializer.deserialize.assert_called_once_with( request.body.decode()) self._model_facade.create.assert_called_once_with(expected_model)
def test_create_item_invalidresource(self): '''This test case ensures an item can not be created if it's invalid.''' resource = Resource(name="Mock Simple Resource", url="/mock-simple-resources", version=1.0, validator=MockSimpleResourceValidator) resource(MockSimpleResourceRoa, self._resources_registry) request_body = {"description": "Simple resource description."} request = Mock() request.body = json.dumps(request_body).encode() self._resources_registry.find_by_url = Mock(return_value=resource) self._json_serializer.deserialize = Mock( return_value=MockSimpleResourceRoa( description=request_body.get("description"))) response = self._controller.create_item(request, version=str(resource.version), resource_url=resource.url) self._assert_resource_error(response, 400, 10010, str(resource.version), resource.url) self._resources_registry.find_by_url.assert_called_once_with( resource.url, resource.version) self._json_serializer.deserialize.assert_called_once_with( request.body.decode())
def test_update_item_nobody(self): '''This test case ensures an item can not be updated without passing a body.''' url = "/simple-resources" version = "1.0" resource = Resource(name="Mock Simple Resource", url=url, version=float(version)) resource(MockSimpleResourceRoa, self._resources_registry) resource_id = 1986 request = Mock() request.body = None self._resources_registry.find_by_url = Mock(return_value=resource) response = self._controller.update_item(request, version, url, resource_id) self._assert_resource_error(response, 400, 10020, version, url) self._resources_registry.find_by_url.assert_called_once_with( url, float(version))
def test_delete_item_dbex(self): '''This test case ensures a delete operation which fails because of a database exception raises a concrete exception.''' url = "/simple-resources" version = "latest" resource_id = "12345" request = Mock() resource = Resource(name="Mock Simple Resource", url=url, version=1.0) resource(MockSimpleResourceRoa, self._resources_registry) self._resources_registry.find_by_url = Mock(return_value=resource) self._model_facade.model_pk_cols = [MockSimpleResourceRoa.id] self._model_facade.find_by_pk = Mock( side_effect=FantasticoDbError("Unexpected db exception")) response = self._controller.delete_item_latest(request, url, resource_id) self._assert_resource_error(response, 400, 10030, version, url) self._resources_registry.find_by_url.assert_called_once_with( url, version) self._model_facade.find_by_pk.assert_called_once_with( {MockSimpleResourceRoa.id: resource_id})
def test_delete_item_itemnotfound(self): '''This test case ensures an item which does not belong to a collection returns a concrete exception response.''' url = "/simple-resources" version = "latest" resource_id = "12345" request = Mock() resource = Resource(name="Mock Simple Resource", url=url, version=1.0) resource(MockSimpleResourceRoa, self._resources_registry) self._resources_registry.find_by_url = Mock(return_value=resource) self._model_facade.model_pk_cols = [MockSimpleResourceRoa.id] self._model_facade.find_by_pk = Mock(return_value=None) response = self._controller.delete_item_latest(request, url, resource_id) self._assert_resource_error(response, 404, 10040, version, url) self._resources_registry.find_by_url.assert_called_once_with( url, version) self._model_facade.find_by_pk.assert_called_once_with( {MockSimpleResourceRoa.id: resource_id})
def test_get_item_unexpected_dbex(self): '''This test case ensures an exception response is received whenever a database exception occurs.''' url = "/simple-resources" version = "1.0" resource = Resource(name="Mock Simple Resource", url=url, version=float(version)) resource(MockSimpleResourceRoa, self._resources_registry) resource_id = 1986 self._resources_registry.find_by_url = Mock(return_value=resource) self._model_facade.model_pk_cols = [MockSimpleResourceRoa.id] self._model_facade.find_by_pk = Mock( side_effect=FantasticoDbError("Unexpected db error.")) response = self._controller.get_item(Mock(), version, url, resource_id) self._assert_resource_error(response, 400, 10030, version, url) self._resources_registry.find_by_url.assert_called_once_with( url, float(version)) self._model_facade.find_by_pk.assert_called_once_with( {MockSimpleResourceRoa.id: resource_id})
def test_get_item_ok(self): '''This test case ensures an item can be correctly retrieved from collection.''' self._controller.validate_security_context = Mock(return_value=None) url = "/simple-resources" version = "1.0" fields = "id,name,description" model = Mock() resource = Resource(name="Mock Simple Resource", url=url, version=float(version)) resource(MockSimpleResourceRoa, self._resources_registry) request = Mock() request.params = {"fields": fields} resource_id = 1986 expected_body = { "id": resource_id, "name": "Test resource", "description": "Simple description." } self._resources_registry.find_by_url = Mock(return_value=resource) self._model_facade.model_pk_cols = [MockSimpleResourceRoa.id] self._model_facade.find_by_pk = Mock(return_value=model) self._json_serializer.serialize = Mock(return_value=expected_body) response = self._controller.get_item(request, version, url, resource_id) self.assertIsNotNone(response) self.assertEqual(200, response.status_code) self.assertEqual("application/json", response.content_type) self._assert_cors_headers(response) self.assertIsNotNone(response.body) body = json.loads(response.body.decode()) self.assertEqual(expected_body, body) self._resources_registry.find_by_url.assert_called_once_with( url, float(version)) self._model_facade.find_by_pk.assert_called_once_with( {MockSimpleResourceRoa.id: resource_id}) self._json_serializer_cls.assert_called_once_with(resource) self._json_serializer.serialize(model, fields) self._controller.validate_security_context.assert_called_once_with( request, "read")
def test_find_resource_by_url_version_notfound(self): '''This test case ensures None is returned if the resource url is found but the requested version is not registered.''' registry = ResourcesRegistry() registry.register_resource( Resource(name="app-setting", url="/app-settings", version="1.0")) resource = registry.find_by_url("/app-settings", 2.0) self.assertIsNone(resource)
def test_unregister_resource_versionnotfound(self): '''This test case ensures no exception is raised if the given resource version is not registered.''' registry = ResourcesRegistry() registry.register_resource( Resource(name="for_test", url="/for_test", version=2.0)) registry.unregister_resource("for_test", 1.0) self.assertIsNone(registry.find_by_name("for_test", 1.0))
def test_unregister_resource_ok(self): '''This test case ensures unregister is ok for registered resources.''' registry = ResourcesRegistry() expected_name = "app-setting" expected_url = "/app-setting" resource1 = Resource(name=expected_name, url=expected_url, version=1.0) resource2 = Resource(name=expected_name, url=expected_url, version=2.0) registry.register_resource(resource1) registry.register_resource(resource2) registry.unregister_resource(expected_name, 2.0) self.assertIsNone(registry.find_by_name(expected_name, 2.0)) self.assertIsNone(registry.find_by_url(expected_url, 2.0)) self.assertEqual(registry.find_by_name(expected_name), resource1) self.assertEqual(registry.find_by_url(expected_url), resource1)
def test_all_resources_list(self): '''This test case ensures registered resources can be listed correctly (sorted by name).''' resource1 = Resource(name="triplex", url="/triplex", version=2.0) resource2 = Resource(name="triplex", url="/triplex", version=1.0) resource3 = Resource(name="abc", url="/abc", version=1.0) registry = ResourcesRegistry() registry.register_resource(resource1) registry.register_resource(resource2) registry.register_resource(resource3) expected_resources = [ resource3, resource3, resource2, resource1, resource1 ] resources = registry.all_resources() self.assertEqual(resources, expected_resources)
def test_check_instantiation(self): '''This test case ensures resource instantiation work as expected (with and without explicit values).''' expected_name = "app-setting" expected_url = "/app-settings" expected_version = 1.0 expected_subresources = {"default_address": ["default_address_id"]} resource = Resource(name=expected_name, url=expected_url, subresources=expected_subresources) resource_explicit = Resource(name=expected_name, url=expected_url, version=expected_version) self.assertEqual(resource.name, resource_explicit.name) self.assertEqual(resource.url, resource_explicit.url) self.assertEqual(resource.version, resource_explicit.version) self.assertEqual(resource.model, resource_explicit.model) self.assertEqual(resource.name, expected_name) self.assertEqual(resource.url, expected_url) self.assertEqual(resource.version, expected_version) self.assertEqual(resource.subresources, expected_subresources) self.assertIsNone(resource.model)
def test_find_resource_by_name_version_notfound(self): '''This test case ensures no exception is raised when we try to retrieve a resource which does not have the version requested registered.''' registry = ResourcesRegistry() registry.register_resource( Resource(name="app-setting", url="/app-settings")) resource = registry.find_by_name("app-setting", 2.0) self.assertIsNone(resource)
def test_update_item_ok(self): '''This test case covers scenario when an item can be updated successfully.''' self._controller.validate_security_context = Mock(return_value=None) expected_body = { "name": "cool name", "description": "incredible simple description" } url = "/simple-resources" version = "latest" resource_id = "12345" request = Mock() request.body = json.dumps(expected_body).encode() resource = Resource(name="Mock Simple Resource", url=url, version=1.0) resource(MockSimpleResourceRoa, self._resources_registry) pk_col = MockSimpleResourceRoa.id model = Mock() self._resources_registry.find_by_url = Mock(return_value=resource) self._json_serializer.deserialize = Mock(return_value=model) self._model_facade.find_by_pk = Mock(return_value=model) self._model_facade.update = Mock(return_value=None) self._model_facade.model_pk_cols = [pk_col] response = self._controller.update_item_latest(request, url, resource_id) self.assertIsNotNone(response) self.assertEqual(204, response.status_code) self.assertEqual("application/json", response.content_type) self._assert_cors_headers(response) self.assertEqual("0", response.headers["Content-Length"]) self.assertEqual(0, len(response.body)) self.assertEqual(resource_id, model.id) self._resources_registry.find_by_url.assert_called_once_with( url, version) self._model_facade.find_by_pk.assert_called_once_with( {MockSimpleResourceRoa.id: resource_id}) self._json_serializer_cls.assert_called_once_with(resource) self._json_serializer.deserialize.assert_called_once_with( json.dumps(expected_body)) self._model_facade.update.assert_called_once_with(model) self._controller.validate_security_context.assert_called_once_with( request, "update")
def _test_resources_listing(self, roa_api): '''This method execute resources listing success scenario. It assers generated urls agains a given roa_api.''' self._settings_facade.get = Mock(return_value=roa_api) from fantastico.contrib.roa_discovery.discovery_controller import RoaDiscoveryController self._discovery_ctrl = RoaDiscoveryController(self._settings_facade, self._registry_cls) self._registry.all_resources = lambda: [Resource(name="Person", url="/persons", version=1.0), Resource(name="Person", url="/persons", version=1.0), Resource(name="Address", url="/addresses", version=1.0), Resource(name="Address", url="/addresses", version=2.0), Resource(name="Address", url="/addresses", version=2.0)] response = self._discovery_ctrl.list_registered_resources(Mock()) self.assertIsNotNone(response) self.assertEqual(response.content_type, "application/json") self.assertEqual(response.charset, "UTF-8") self.assertEqual(response.headers["Access-Control-Allow-Origin"], "*") self.assertEqual(response.headers["Access-Control-Allow-Methods"], "OPTIONS,GET,POST,PUT,DELETE") resources = json.loads(response.body.decode()) self.assertIsNotNone(resources) self.assertEqual(resources["Person"]["1.0"], "%s/1.0/persons" % roa_api) self.assertEqual(resources["Person"]["latest"], "%s/latest/persons" % roa_api) self.assertEqual(resources["Address"]["1.0"], "%s/1.0/addresses" % roa_api) self.assertEqual(resources["Address"]["2.0"], "%s/2.0/addresses" % roa_api) self.assertEqual(resources["Address"]["latest"], "%s/latest/addresses" % roa_api) self._registry_cls.assert_called_once_with() self._settings_facade.get.assert_called_once_with("roa_api")
def test_create_item_ok(self): '''This test case ensures a valid resource can be created correctly.''' self._controller.validate_security_context = Mock(return_value=None) resource = Resource(name="Mock Simple Resource", url="/mock-simple-resources", version=1.0) resource(MockSimpleResourceRoa, self._resources_registry) request_body = { "name": "simple-resource1", "description": "Simple resource description." } expected_model = MockSimpleResourceRoa( name=request_body.get("name"), description=request_body.get("description")) expected_id = 123 request = Mock() request.body = json.dumps(request_body).encode() self._resources_registry.find_by_url = Mock(return_value=resource) self._json_serializer.deserialize = Mock(return_value=expected_model) self._model_facade.create = Mock(return_value=[expected_id]) response = self._controller.create_item(request, str(resource.version), resource.url) self.assertIsNotNone(resource) self.assertEqual(201, response.status_code) self.assertEqual("application/json", response.content_type) self._assert_cors_headers(response) self.assertEqual("0", response.headers["Content-Length"]) self.assertEqual( "/api/%s%s/%s" % (resource.version, resource.url, expected_id), response.headers["Location"]) self._resources_registry.find_by_url.assert_called_once_with( resource.url, resource.version) self._json_serializer.deserialize.assert_called_once_with( request.body.decode()) self._model_facade.create.assert_called_once_with(expected_model) self._controller.validate_security_context.assert_called_once_with( request, "create")
def test_unregister_resource_latestnotallowed(self): '''This test case ensures that nothing happens if latest is given as version.''' registry = ResourcesRegistry() expected_name = "app-setting" expected_url = "/app-setting" resource1 = Resource(name=expected_name, url=expected_url, version=1.0) registry.register_resource(resource1) registry.unregister_resource(expected_name, version="latest") self.assertEqual(registry.find_by_name(expected_name), resource1) self.assertEqual(registry.find_by_url(expected_url), resource1)
def _find_resource_by_url(self, url, version): '''This method provides a test case template for find by url method.''' resource = Resource(name=url[1:-1], url=url) registry = ResourcesRegistry() registry.register_resource(resource) if version != "latest": found_resource = registry.find_by_url(url, version) else: found_resource = registry.find_by_url(url) self.assertEqual(resource.name, found_resource.name) self.assertEqual(resource.version, found_resource.version) self.assertEqual(resource.url, found_resource.url) self.assertEqual(resource.model, found_resource.model)
def _find_resource_by_name(self, name, version): '''This method provides a test case template for find by name method.''' resource = Resource(name=name, url="/%ss" % name) registry = ResourcesRegistry() registry.register_resource(resource) if version != "latest": found_resource = registry.find_by_name(name, version) else: found_resource = registry.find_by_name(name) self.assertEqual(resource.name, found_resource.name) self.assertEqual(resource.version, found_resource.version) self.assertEqual(resource.url, found_resource.url) self.assertEqual(resource.model, found_resource.model)
def test_check_call(self): '''This test case ensures call method correctly registers a resource to a given resource.''' expected_name = "app-setting" expected_url = "/app-settings" registry = Mock() model = Mock() resource = Resource(name=expected_name, url=expected_url) self.assertEqual(resource(model, resources_registry=registry), model) self.assertEqual(resource.name, expected_name) self.assertEqual(resource.url, expected_url) self.assertEqual(resource.version, 1.0) self.assertEqual(resource.model, model) registry.register_resource.assert_called_once_with(resource)
def test_unregister_resource_noremaining_version(self): '''This test case ensures latest version is also removed when all resource versions are removed.''' registry = ResourcesRegistry() expected_name = "app-setting" expected_url = "/app-setting" resource1 = Resource(name=expected_name, url=expected_url, version=1.0) registry.register_resource(resource1) self.assertEqual(registry.find_by_name(expected_name), resource1) self.assertEqual(registry.find_by_url(expected_url), resource1) registry.unregister_resource(expected_name, version=1.0) self.assertIsNone(registry.find_by_name(expected_name)) self.assertIsNone(registry.find_by_url(expected_url))
def test_update_item_dbex(self): '''This test case covers scenario when an item can not be updated because of a db exception.''' expected_body = { "name": "cool name", "description": "incredible simple description" } url = "/simple-resources" version = "1.0" resource_id = "12345" request = Mock() request.body = json.dumps(expected_body).encode() resource = Resource(name="Mock Simple Resource", url=url, version=float(version)) resource(MockSimpleResourceRoa, self._resources_registry) pk_col = Mock() pk_col.name = "id" model = Mock() self._resources_registry.find_by_url = Mock(return_value=resource) self._json_serializer.deserialize = Mock(return_value=model) self._model_facade.update = Mock( side_effect=FantasticoDbError("Unexpected exception")) self._model_facade.model_pk_cols = [pk_col] response = self._controller.update_item(request, version, url, resource_id) self._assert_resource_error(response, 400, 10030, version, url) self.assertEqual(resource_id, model.id) self._resources_registry.find_by_url.assert_called_once_with( url, float(version)) self._json_serializer_cls.assert_called_once_with(resource) self._json_serializer.deserialize.assert_called_once_with( json.dumps(expected_body))
def test_update_item_itemnotfound(self): '''This test case covers scenario when we want to update an item which does not exist.''' expected_body = { "name": "cool name", "description": "incredible simple description" } url = "/simple-resources" version = "1.0" resource_id = "12345" request = Mock() request.body = json.dumps(expected_body).encode() resource = Resource(name="Mock Simple Resource", url=url, version=float(version)) resource(MockSimpleResourceRoa, self._resources_registry) pk_col = MockSimpleResourceRoa.id model = Mock() self._resources_registry.find_by_url = Mock(return_value=resource) self._json_serializer.deserialize = Mock(return_value=model) self._model_facade.find_by_pk = Mock(return_value=None) self._model_facade.model_pk_cols = [pk_col] response = self._controller.update_item(request, version, url, resource_id) self._assert_resource_error(response, 404, 10040, version, url) self._resources_registry.find_by_url.assert_called_once_with( url, float(version)) self._model_facade.find_by_pk.assert_called_once_with( {MockSimpleResourceRoa.id: resource_id}) self._json_serializer_cls.assert_called_once_with(resource) self._json_serializer.deserialize.assert_called_once_with( json.dumps(expected_body))
def test_delete_item_ok(self): '''This test case ensures an existing item can be deleted successfully.''' self._controller.validate_security_context = Mock(return_value=None) url = "/simple-resources" version = "1.0" resource_id = "12345" request = Mock() resource = Resource(name="Mock Simple Resource", url=url, version=1.0) resource(MockSimpleResourceRoa, self._resources_registry) model = Mock() self._resources_registry.find_by_url = Mock(return_value=resource) self._model_facade.model_pk_cols = [MockSimpleResourceRoa.id] self._model_facade.find_by_pk = Mock(return_value=model) response = self._controller.delete_item(request, version, url, resource_id) self.assertIsNotNone(response) self.assertEqual(204, response.status_code) self.assertEqual("application/json", response.content_type) self._assert_cors_headers(response) self.assertEqual("0", response.headers["Content-Length"]) self.assertEqual(0, len(response.body)) self._resources_registry.find_by_url.assert_called_once_with( url, float(version)) self._model_facade.find_by_pk.assert_called_once_with( {MockSimpleResourceRoa.id: resource_id}) self._model_facade.delete.assert_called_once_with(model) self._controller.validate_security_context.assert_called_once_with( request, "delete")