diff --git a/src/Service.Tests/SqlTests/RestApiTests/Delete/DeleteApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Delete/DeleteApiTestBase.cs index eb5d8c2f59..5d19ab8435 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Delete/DeleteApiTestBase.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Delete/DeleteApiTestBase.cs @@ -31,7 +31,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationEntityName, sqlQuery: null, - controller: _restController, operationType: Operation.Delete, requestBody: null, expectedStatusCode: HttpStatusCode.NoContent @@ -55,7 +54,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationMappingEntity, sqlQuery: null, - controller: _restController, operationType: Operation.Delete, requestBody: null, expectedStatusCode: HttpStatusCode.NoContent @@ -80,7 +78,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationUniqueCharactersEntity, sqlQuery: null, - controller: _restController, operationType: Operation.Delete, requestBody: null, expectedStatusCode: HttpStatusCode.NoContent @@ -105,10 +102,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Delete, requestBody: string.Empty, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Not Found", expectedStatusCode: HttpStatusCode.NotFound, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.EntityNotFound.ToString() @@ -130,10 +126,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Delete, requestBody: string.Empty, - exception: true, + exceptionExpected: true, expectedErrorMessage: "The request is invalid since the primary keys: title requested were not found in the entity definition.", expectedStatusCode: HttpStatusCode.NotFound, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.EntityNotFound.ToString() @@ -154,10 +149,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Delete, requestBody: string.Empty, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Primary Key for DELETE requests is required.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString() @@ -186,10 +180,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Delete, requestBody: string.Empty, - exception: true, + exceptionExpected: true, expectedErrorMessage: message, expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString() diff --git a/src/Service.Tests/SqlTests/RestApiTests/Delete/MsSqlDeleteApiTest.cs b/src/Service.Tests/SqlTests/RestApiTests/Delete/MsSqlDeleteApiTest.cs index 87f5455d54..9f0467e7b9 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Delete/MsSqlDeleteApiTest.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Delete/MsSqlDeleteApiTest.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Delete @@ -34,16 +32,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MSSQL; await InitializeTestFixture(context); - // Setup REST Components - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Delete/MySqlDeleteApiTest.cs b/src/Service.Tests/SqlTests/RestApiTests/Delete/MySqlDeleteApiTest.cs index 166872b71a..7ddc824455 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Delete/MySqlDeleteApiTest.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Delete/MySqlDeleteApiTest.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Delete @@ -36,15 +34,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MYSQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Delete/PostgreSqlDeleteApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Delete/PostgreSqlDeleteApiTests.cs index c944732376..848558b5b3 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Delete/PostgreSqlDeleteApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Delete/PostgreSqlDeleteApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Delete @@ -36,15 +34,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.POSTGRESQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } #endregion diff --git a/src/Service.Tests/SqlTests/RestApiTests/Find/FindApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Find/FindApiTestBase.cs index 51bbb5a5b3..f4b471a587 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Find/FindApiTestBase.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Find/FindApiTestBase.cs @@ -30,8 +30,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: "id/2", queryString: string.Empty, entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindByIdTest)), - controller: _restController + sqlQuery: GetQuery(nameof(FindByIdTest)) ); } @@ -47,7 +46,6 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationProcedureFindMany_EntityName, sqlQuery: GetQuery("FindManyStoredProcedureTest"), - controller: _restController, expectJson: false ); } @@ -64,7 +62,6 @@ await SetupAndRunRestApiTest( queryString: "?id=1", entity: _integrationProcedureFindOne_EntityName, sqlQuery: GetQuery("FindOneStoredProcedureTestUsingParameter"), - controller: _restController, expectJson: false ); } @@ -82,16 +79,14 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: string.Empty, entity: _emptyTableEntityName, - sqlQuery: GetQuery("FindEmptyTable"), - controller: _restController + sqlQuery: GetQuery("FindEmptyTable") ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=1 ne 1", entity: _integrationEntityName, - sqlQuery: GetQuery("FindEmptyResultSetWithQueryFilter"), - controller: _restController + sqlQuery: GetQuery("FindEmptyResultSetWithQueryFilter") ); } @@ -107,8 +102,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: string.Empty, entity: _integrationUniqueCharactersEntity, - sqlQuery: GetQuery("FindOnTableWithUniqueCharacters"), - controller: _restController); + sqlQuery: GetQuery("FindOnTableWithUniqueCharacters")); } /// @@ -122,24 +116,21 @@ await SetupAndRunRestApiTest( primaryKeyRoute: "id/2", queryString: string.Empty, entity: _simple_all_books, - sqlQuery: GetQuery("FindViewAll"), - controller: _restController + sqlQuery: GetQuery("FindViewAll") ); await SetupAndRunRestApiTest( primaryKeyRoute: "categoryid/2/pieceid/1", queryString: string.Empty, entity: _simple_subset_stocks, - sqlQuery: GetQuery("FindViewSelected"), - controller: _restController + sqlQuery: GetQuery("FindViewSelected") ); await SetupAndRunRestApiTest( primaryKeyRoute: "id/2", queryString: string.Empty, entity: _composite_subset_bookPub, - sqlQuery: GetQuery("FindViewComposite"), - controller: _restController + sqlQuery: GetQuery("FindViewComposite") ); } @@ -154,37 +145,36 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id ge 4", entity: _simple_all_books, - sqlQuery: GetQuery("FindTestWithFilterQueryOneGeFilterOnView"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneGeFilterOnView") + ); await SetupAndRunRestApiTest( primaryKeyRoute: "id/1", queryString: "?$select=id,title", entity: _simple_all_books, - sqlQuery: GetQuery("FindByIdTestWithQueryStringFieldsOnView"), - controller: _restController + sqlQuery: GetQuery("FindByIdTestWithQueryStringFieldsOnView") ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=pieceid eq 1", entity: _simple_subset_stocks, - sqlQuery: GetQuery("FindTestWithFilterQueryStringOneEqFilterOnView"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryStringOneEqFilterOnView") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=not (categoryid gt 1)", entity: _simple_subset_stocks, - sqlQuery: GetQuery("FindTestWithFilterQueryOneNotFilterOnView"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneNotFilterOnView") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter= id lt 5", entity: _composite_subset_bookPub, - sqlQuery: GetQuery("FindTestWithFilterQueryOneLtFilterOnView"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneLtFilterOnView") + ); } /// @@ -198,8 +188,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: "id/1", queryString: "?$select=id,title", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindByIdTestWithQueryStringFields)), - controller: _restController + sqlQuery: GetQuery(nameof(FindByIdTestWithQueryStringFields)) ); } @@ -214,8 +203,8 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$select=id", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithQueryStringOneField)), - controller: _restController); + sqlQuery: GetQuery(nameof(FindTestWithQueryStringOneField)) + ); } @@ -230,8 +219,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: string.Empty, entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithQueryStringAllFields)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithQueryStringAllFields)) ); } @@ -246,62 +234,61 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id eq 1", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryStringOneEqFilter"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryStringOneEqFilter") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=2 eq id", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryStringValueFirstOneEqFilter"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryStringValueFirstOneEqFilter") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id gt 3", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryOneGtFilter"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneGtFilter") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id ge 4", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryOneGeFilter"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneGeFilter") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id lt 5", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryOneLtFilter"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneLtFilter") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id le 4", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryOneLeFilter"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneLeFilter") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id ne 3", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryOneNeFilter"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneNeFilter") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=not (id lt 2)", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryOneNotFilter"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneNotFilter") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=not (title eq null)", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryOneRightNullEqFilter"), - controller: _restController); + sqlQuery: GetQuery("FindTestWithFilterQueryOneRightNullEqFilter") + ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=null ne title", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestWithFilterQueryOneLeftNullNeFilter"), - controller: _restController + sqlQuery: GetQuery("FindTestWithFilterQueryOneLeftNullNeFilter") ); } @@ -316,8 +303,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id lt 3 and id gt 1", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringSingleAndFilter)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringSingleAndFilter)) ); } @@ -332,8 +318,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id lt 3 or id gt 4", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringSingleOrFilter)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringSingleOrFilter)) ); } @@ -348,8 +333,8 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id lt 4 and id gt 1 and title ne 'Awesome book'", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringMultipleAndFilters)), - controller: _restController); + sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringMultipleAndFilters)) + ); } @@ -364,8 +349,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=id eq 1 or id eq 2 or id eq 3", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringMultipleOrFilters)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringMultipleOrFilters)) ); } @@ -380,8 +364,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=(id gt 2 and id lt 4) or (title eq 'Awesome book')", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringMultipleAndOrFilters)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringMultipleAndOrFilters)) ); } @@ -396,8 +379,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=(not (id lt 3) or id lt 4) or not (title eq 'Awesome book')", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringMultipleNotAndOrFilters)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringMultipleNotAndOrFilters)) ); } @@ -413,8 +395,7 @@ await SetupAndRunRestApiTest( queryString: "?$filter=id eq (publisher_id gt 1)", entity: _integrationEntityName, sqlQuery: GetQuery(nameof(FindTestWithFilterQueryStringSingleAndFilter)), - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "A binary operator with incompatible types was detected. " + "Found operand types 'Edm.Int32' and 'Edm.Boolean' for operator kind 'Equal'.", expectedStatusCode: HttpStatusCode.BadRequest @@ -428,8 +409,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: "id/567/book_id/1", queryString: "?$select=id,content", entity: _entityWithCompositePrimaryKey, - sqlQuery: GetQuery(nameof(FindTestWithPrimaryKeyContainingForeignKey)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithPrimaryKeyContainingForeignKey)) ); } @@ -447,7 +427,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1", entity: _integrationEntityName, sqlQuery: GetQuery(nameof(FindTestWithFirstSingleKeyPagination)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(after)}", paginated: true ); @@ -468,7 +447,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1", entity: _entityWithCompositePrimaryKey, sqlQuery: GetQuery(nameof(FindTestWithFirstMultiKeyPagination)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true ); @@ -486,8 +464,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: $"?$after={HttpUtility.UrlEncode(after)}", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithAfterSingleKeyPagination)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithAfterSingleKeyPagination)) ); } @@ -505,8 +482,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: $"?$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", entity: _entityWithCompositePrimaryKey, - sqlQuery: GetQuery(nameof(FindTestWithAfterMultiKeyPagination)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithAfterMultiKeyPagination)) ); } @@ -524,7 +500,6 @@ await SetupAndRunRestApiTest( queryString: $"?$first=1", entity: _integrationEntityName, sqlQuery: GetQuery(nameof(FindTestWithPaginationVerifSinglePrimaryKeyInAfter)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(after)}", paginated: true ); @@ -545,7 +520,6 @@ await SetupAndRunRestApiTest( queryString: $"?$first=1", entity: _entityWithCompositePrimaryKey, sqlQuery: GetQuery(nameof(FindTestWithPaginationVerifMultiplePrimaryKeysInAfter)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true ); @@ -562,8 +536,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$orderby=title", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithQueryStringAllFieldsOrderByAsc)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithQueryStringAllFieldsOrderByAsc)) ); } @@ -578,8 +551,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$orderby=fancyName", entity: _integrationMappingDifferentEntity, - sqlQuery: GetQuery(nameof(FindTestWithQueryStringAllFieldsMappedEntityOrderByAsc)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithQueryStringAllFieldsMappedEntityOrderByAsc)) ); } @@ -595,8 +567,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$orderby='ID Number'", entity: _integrationEntityHasColumnWithSpace, - sqlQuery: GetQuery(nameof(FindTestWithQueryStringSpaceInNamesOrderByAsc)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithQueryStringSpaceInNamesOrderByAsc)) ); } @@ -616,7 +587,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1&$orderby='Last Name'", entity: _integrationEntityHasColumnWithSpace, sqlQuery: GetQuery(nameof(FindTestWithFirstAndSpacedColumnOrderBy)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true @@ -634,8 +604,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$orderby=publisher_id desc", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestWithQueryStringAllFieldsOrderByDesc)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithQueryStringAllFieldsOrderByDesc)) ); } @@ -654,7 +623,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1&$orderby=title", entity: _integrationEntityName, sqlQuery: GetQuery(nameof(FindTestWithFirstSingleKeyPaginationAndOrderBy)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true ); @@ -674,7 +642,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1&$orderby=id", entity: _integrationEntityName, sqlQuery: GetQuery(nameof(FindTestWithFirstSingleKeyIncludedInOrderByAndPagination)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(after)}", paginated: true ); @@ -694,7 +661,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=2&$orderby=id", entity: _integrationEntityName, sqlQuery: GetQuery(nameof(FindTestWithFirstTwoOrderByAndPagination)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(after)}", paginated: true ); @@ -717,7 +683,6 @@ await SetupAndRunRestApiTest( queryString: $"?$first=2&$orderby=birthdate, name, id desc", entity: _integrationTieBreakEntity, sqlQuery: GetQuery(nameof(FindTestWithFirstTwoVerifyAfterFormedCorrectlyWithOrderBy)), - controller: _restController, expectedAfterQueryString: after, paginated: true ); @@ -741,7 +706,6 @@ await SetupAndRunRestApiTest( queryString: $"?$first=2&$orderby=birthdate, name, id{after}", entity: _integrationTieBreakEntity, sqlQuery: GetQuery(nameof(FindTestWithFirstTwoVerifyAfterBreaksTieCorrectlyWithOrderBy)), - controller: _restController, verifyNumRecords: _numRecordsReturnedFromTieBreakTable ); } @@ -762,7 +726,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1&$orderby=id desc, book_id", entity: _entityWithCompositePrimaryKey, sqlQuery: GetQuery(nameof(FindTestWithFirstMultiKeyIncludeAllInOrderByAndPagination)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true ); @@ -784,7 +747,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1&$orderby=book_id", entity: _entityWithCompositePrimaryKey, sqlQuery: GetQuery(nameof(FindTestWithFirstMultiKeyIncludeOneInOrderByAndPagination)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true ); @@ -808,7 +770,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1&$orderby=publisher_id desc, title desc", entity: _integrationEntityName, sqlQuery: GetQuery(nameof(FindTestWithFirstAndMultiColumnOrderBy)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true ); @@ -830,7 +791,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1&$orderby=publisher_id desc", entity: _integrationEntityName, sqlQuery: GetQuery(nameof(FindTestWithFirstAndTiedColumnOrderBy)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true ); @@ -848,15 +808,13 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$orderby=id desc, publisher_id", entity: _integrationEntityName, - sqlQuery: GetQuery(nameof(FindTestVerifyMaintainColumnOrderForOrderBy)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestVerifyMaintainColumnOrderForOrderBy)) ); await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$orderby=publisher_id, id desc", entity: _integrationEntityName, - sqlQuery: GetQuery("FindTestVerifyMaintainColumnOrderForOrderByInReverse"), - controller: _restController + sqlQuery: GetQuery("FindTestVerifyMaintainColumnOrderForOrderByInReverse") ); } @@ -877,7 +835,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1&$orderby=content desc", entity: _entityWithCompositePrimaryKey, sqlQuery: GetQuery(nameof(FindTestWithFirstMultiKeyPaginationAndOrderBy)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true ); @@ -897,8 +854,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: string.Empty, entity: _integrationMappingEntity, - sqlQuery: GetQuery(nameof(FindTestWithMappedFieldsToBeReturned)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithMappedFieldsToBeReturned)) ); } @@ -916,8 +872,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$select=Scientific Name", entity: _integrationMappingEntity, - sqlQuery: GetQuery(nameof(FindTestWithSingleMappedFieldsToBeReturned)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithSingleMappedFieldsToBeReturned)) ); } @@ -935,8 +890,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$select=treeId", entity: _integrationMappingEntity, - sqlQuery: GetQuery(nameof(FindTestWithUnMappedFieldsToBeReturned)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithUnMappedFieldsToBeReturned)) ); } @@ -953,8 +907,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$filter=fancyName eq 'Tsuga terophylla'", entity: _integrationMappingDifferentEntity, - sqlQuery: GetQuery(nameof(FindTestWithDifferentMappedFieldsAndFilter)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithDifferentMappedFieldsAndFilter)) ); } @@ -972,8 +925,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: "?$orderby=fancyName", entity: _integrationMappingDifferentEntity, - sqlQuery: GetQuery(nameof(FindTestWithDifferentMappedFieldsAndOrderBy)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithDifferentMappedFieldsAndOrderBy)) ); } @@ -994,7 +946,6 @@ await SetupAndRunRestApiTest( queryString: "?$first=1&$orderby=fancyName", entity: _integrationMappingDifferentEntity, sqlQuery: GetQuery(nameof(FindTestWithDifferentMappingFirstSingleKeyPaginationAndOrderBy)), - controller: _restController, expectedAfterQueryString: $"&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", paginated: true ); @@ -1016,8 +967,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: string.Empty, queryString: $"?$orderby=fancyName,treeId&$after={HttpUtility.UrlEncode(SqlPaginationUtil.Base64Encode(after))}", entity: _integrationMappingDifferentEntity, - sqlQuery: GetQuery(nameof(FindTestWithDifferentMappingAfterSingleKeyPaginationAndOrderBy)), - controller: _restController + sqlQuery: GetQuery(nameof(FindTestWithDifferentMappingAfterSingleKeyPaginationAndOrderBy)) ); } #endregion @@ -1037,8 +987,7 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationProcedureFindMany_EntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Primary key route not supported for this entity.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1056,8 +1005,7 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationProcedureFindOne_EntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request. Missing required procedure parameters: id", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1076,8 +1024,7 @@ await SetupAndRunRestApiTest( queryString: "?param=value", entity: _integrationProcedureFindMany_EntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request. Contained unexpected fields: param", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1088,8 +1035,7 @@ await SetupAndRunRestApiTest( queryString: "?id=1¶m=value", entity: _integrationProcedureFindOne_EntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request. Contained unexpected fields: param", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1108,8 +1054,7 @@ await SetupAndRunRestApiTest( queryString: "?$first=0", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid number of items requested, $first must be an integer greater than 0. Actual value: 0", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1133,8 +1078,7 @@ await SetupAndRunRestApiTest( queryString: $"?$filter={keyword}{value} {compareTo}", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "$filter query parameter is not well formed.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: "BadRequest" @@ -1149,8 +1093,7 @@ await SetupAndRunRestApiTest( queryString: "?$filter=pq ge 4", entity: _simple_all_books, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Could not find a property named 'pq' on type 'default_namespace.{_simple_all_books}.{GetDefaultSchemaForEdmModel()}books_view_all'.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1160,8 +1103,7 @@ await SetupAndRunRestApiTest( queryString: "?$filter=pq le 4", entity: _simple_subset_stocks, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Could not find a property named 'pq' on type 'default_namespace.{_simple_subset_stocks}.{GetDefaultSchemaForEdmModel()}stocks_view_selected'.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1172,8 +1114,7 @@ await SetupAndRunRestApiTest( queryString: "?$filter=not (title gt 1)", entity: _composite_subset_bookPub, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Could not find a property named 'title' on type 'default_namespace.{_composite_subset_bookPub}.{GetDefaultSchemaForEdmModel()}books_publishers_view_composite'.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1190,8 +1131,7 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "The request is invalid since it contains a primary key with no value specified.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1211,8 +1151,7 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Support for url template with implicit primary key field names is not yet added.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1230,8 +1169,7 @@ await SetupAndRunRestApiTest( queryString: "?$select=id,content", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid field to be returned requested: content", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1254,8 +1192,7 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _nonExistentEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"{_nonExistentEntityName} is not a valid entity.", expectedStatusCode: HttpStatusCode.NotFound, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.EntityNotFound.ToString() @@ -1270,8 +1207,7 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: integrationEntityNameIncorrectCase, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"{integrationEntityNameIncorrectCase} is not a valid entity.", expectedStatusCode: HttpStatusCode.NotFound, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.EntityNotFound.ToString() @@ -1291,8 +1227,7 @@ await SetupAndRunRestApiTest( queryString: "?$select=id,null", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid Field name: null or white space", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString() @@ -1311,8 +1246,7 @@ await SetupAndRunRestApiTest( queryString: "?$select=", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid Field name: null or white space", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString() @@ -1330,8 +1264,7 @@ await SetupAndRunRestApiTest( queryString: "?$orderby=id random", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: HttpUtility.UrlDecode("Syntax error at position 9 in \u0027id random\u0027."), expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1348,8 +1281,7 @@ await SetupAndRunRestApiTest( queryString: "?$orderby=Pinecone", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Could not find a property named 'Pinecone' on type 'default_namespace.{_integrationEntityName}.{GetDefaultSchemaForEdmModel()}books'.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1367,8 +1299,7 @@ await SetupAndRunRestApiTest( queryString: "?$orderby='Large Pinecone'", entity: _integrationEntityHasColumnWithSpace, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Invalid orderby column requested: Large Pinecone.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1386,8 +1317,7 @@ await SetupAndRunRestApiTest( queryString: "?orderby=id", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Invalid Query Parameter: orderby", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1404,8 +1334,7 @@ await SetupAndRunRestApiTest( queryString: "?$orderby=null", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "OrderBy property is not supported.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1426,8 +1355,7 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationBrokenMappingEntity, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "The request is invalid since the primary keys: spores requested were not found in the entity definition.", expectedStatusCode: HttpStatusCode.NotFound, expectedSubStatusCode: "EntityNotFound" @@ -1449,8 +1377,7 @@ await SetupAndRunRestApiTest( queryString: "?$select=hazards", entity: _integrationBrokenMappingEntity, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid field to be returned requested: hazards", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: "BadRequest" @@ -1471,8 +1398,7 @@ await SetupAndRunRestApiTest( queryString: "?$select=species", entity: _integrationMappingEntity, sqlQuery: GetQuery(nameof(FindTestWithUnMappedFieldsToBeReturned)), - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid field to be returned requested: species", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1510,8 +1436,7 @@ await SetupAndRunRestApiTest( queryString: $"?$select=id", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: message, expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1546,8 +1471,7 @@ await SetupAndRunRestApiTest( queryString: $"?$select={sqlInjection}", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Invalid field to be returned requested: {sqlInjection}", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -1582,8 +1506,7 @@ await SetupAndRunRestApiTest( queryString: $"?$select={sqlInjection}", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Invalid field to be returned requested: {sqlInjection}", expectedStatusCode: HttpStatusCode.BadRequest ); diff --git a/src/Service.Tests/SqlTests/RestApiTests/Find/MsSqlFindApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Find/MsSqlFindApiTests.cs index ada887e31d..7ace3400e3 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Find/MsSqlFindApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Find/MsSqlFindApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Find @@ -414,16 +412,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MSSQL; await InitializeTestFixture(context); - // Setup REST Components - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Find/MySqlFindApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Find/MySqlFindApiTests.cs index 34430806fc..bc0ac02340 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Find/MySqlFindApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Find/MySqlFindApiTests.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Find @@ -753,15 +751,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MYSQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Find/PostgreSqlFindApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Find/PostgreSqlFindApiTests.cs index cdbd7976c1..ba312d2432 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Find/PostgreSqlFindApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Find/PostgreSqlFindApiTests.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Find @@ -659,15 +657,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.POSTGRESQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } #endregion diff --git a/src/Service.Tests/SqlTests/RestApiTests/Insert/InsertApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Insert/InsertApiTestBase.cs index a329a0b6b4..4f6cfd006e 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Insert/InsertApiTestBase.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Insert/InsertApiTestBase.cs @@ -30,7 +30,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationEntityName, sqlQuery: GetQuery(nameof(InsertOneTest)), - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -50,7 +49,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("InsertOneInCompositeNonAutoGenPKTest"), - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -79,7 +77,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationUniqueCharactersEntity, sqlQuery: GetQuery(nameof(InsertOneUniqueCharactersTest)), - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -107,7 +104,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationMappingEntity, sqlQuery: GetQuery(nameof(InsertOneWithMappingTest)), - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -134,7 +130,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _entityWithCompositePrimaryKey, sqlQuery: GetQuery(nameof(InsertOneInCompositeKeyTableTest)), - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -152,7 +147,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _entityWithCompositePrimaryKey, sqlQuery: GetQuery("InsertOneInDefaultTestTable"), - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -178,7 +172,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("InsertOneWithNullFieldValue"), - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -210,7 +203,6 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: GetQuery(query), - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -236,10 +228,9 @@ await SetupAndRunRestApiTest( queryString: "?/id/5001", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Query string for POST requests is an invalid url.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -262,10 +253,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Mutation operation on many instances of an entity in a single request are not yet supported.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: "BadRequest" @@ -281,7 +271,7 @@ public virtual async Task InsertOneWithInvalidTypeInJsonBodyTest() string requestBody = @" { ""title"": [""My New Book"", ""Another new Book"", {""author"": ""unknown""}], - ""publisher_id"": [1234, 4321] + ""publisher_id"": [1234,4321] }"; await SetupAndRunRestApiTest( @@ -289,11 +279,10 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, - expectedErrorMessage: "Parameter \"[1234, 4321]\" cannot be resolved as column \"publisher_id\" with type \"Int32\".", + exceptionExpected: true, + expectedErrorMessage: "Parameter \"[1234,4321]\" cannot be resolved as column \"publisher_id\" with type \"Int32\".", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: "BadRequest" ); @@ -313,10 +302,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request body. Missing field in body: title.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -339,10 +327,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request body. Field not allowed in body: id.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -365,10 +352,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integration_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request body. Missing field in body: id.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: "BadRequest" @@ -393,10 +379,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integration_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request body. Missing field in body: title.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: "BadRequest" @@ -413,10 +398,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request body. Missing field in body: categoryName.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: "BadRequest" @@ -440,10 +424,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid value for field piecesRequired in request body.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -462,10 +445,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid value for field categoryName in request body.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -494,9 +476,8 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationBrokenMappingEntity, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Insert, - exception: true, + exceptionExpected: true, requestBody: requestBody, expectedErrorMessage: "Invalid request body. Contained unexpected fields in body: hazards", expectedStatusCode: HttpStatusCode.BadRequest, diff --git a/src/Service.Tests/SqlTests/RestApiTests/Insert/MsSqlInsertApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Insert/MsSqlInsertApiTests.cs index 794c18cc24..da6d97537a 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Insert/MsSqlInsertApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Insert/MsSqlInsertApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Insert @@ -146,16 +144,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MSSQL; await InitializeTestFixture(context); - // Setup REST Components - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Insert/MySqlInsertApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Insert/MySqlInsertApiTests.cs index cf41f0606e..593322ecd9 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Insert/MySqlInsertApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Insert/MySqlInsertApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Insert @@ -171,15 +169,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MYSQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Insert/PostgreSqlInsertApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Insert/PostgreSqlInsertApiTests.cs index a8b806723f..563f9b842f 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Insert/PostgreSqlInsertApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Insert/PostgreSqlInsertApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Insert @@ -168,15 +166,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.POSTGRESQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } #endregion diff --git a/src/Service.Tests/SqlTests/RestApiTests/OtherRestApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/OtherRestApiTests.cs index 0d8337b102..15bde0afd2 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/OtherRestApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/OtherRestApiTests.cs @@ -1,13 +1,8 @@ using System; using System.Net; -using System.Reflection; +using System.Net.Http; using System.Text; using System.Threading.Tasks; -using Azure.DataApiBuilder.Config; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests @@ -39,16 +34,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MSSQL; await InitializeTestFixture(context); - // Setup REST Components - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// @@ -74,8 +59,7 @@ await SetupAndRunRestApiTest( queryString: "?$select=id,content", entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid field to be returned requested: content", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -90,53 +74,29 @@ await SetupAndRunRestApiTest( [TestMethod] public async Task HandleAndExecuteUnsupportedOperationUnitTestAsync() { - string expected = "{\"error\":{\"code\":\"BadRequest\",\"message\":\"This operation is not supported.\",\"status\":400}}"; - // need header to instantiate identity in controller - HeaderDictionary headers = new(); - headers.Add("x-ms-client-principal", Convert.ToBase64String(Encoding.UTF8.GetBytes("{\"hello\":\"world\"}"))); - - ConfigureRestController(_restController, string.Empty, Operation.None); - + string expectedBody = string.Empty; // Setup params to invoke function with // Must use valid entity name string path = "api"; string entityName = "Book"; - Operation operationType = Operation.None; - string primaryKeyRoute = string.Empty; + HttpMethod method = HttpMethod.Head; - // Reflection to invoke a private method to unit test all code paths - PrivateObject testObject = new(_restController); - IActionResult actionResult = await testObject.Invoke("HandleOperation", new object[] { $"{path}/{entityName}/{primaryKeyRoute}", operationType }); - SqlTestHelper.VerifyResult(actionResult, expected, System.Net.HttpStatusCode.BadRequest, string.Empty); - } + // Since primarykey route and querystring are empty for this test, end point would only comprise + // of path and entity name. + string restEndPoint = path + "/" + entityName; - #region Private helpers + HttpRequestMessage request = new(method, restEndPoint); + // need header to instantiate identity in controller + request.Headers.Add("x-ms-client-principal", Convert.ToBase64String(Encoding.UTF8.GetBytes("{\"hello\":\"world\"}"))); - /// - /// Helper function uses reflection to invoke - /// private methods from outside class. - /// Expects async method returning Task. - /// - class PrivateObject - { - private readonly object _classToInvoke; - public PrivateObject(object classToInvoke) - { - _classToInvoke = classToInvoke; - } + // Send request to the engine. + HttpResponseMessage response = await HttpClient.SendAsync(request); - public Task Invoke(string privateMethodName, params object[] privateMethodArgs) - { - MethodInfo methodInfo = _classToInvoke.GetType().GetMethod(privateMethodName, BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - if (methodInfo is null) - { - throw new System.Exception($"{privateMethodName} not found in class '{_classToInvoke.GetType()}'"); - } + // Read response as string. + string responseBody = await response.Content.ReadAsStringAsync(); - return (Task)methodInfo.Invoke(_classToInvoke, privateMethodArgs); - } + // Assert that expectedBody and responseBody are the same. + Assert.AreEqual(expectedBody, responseBody); } - - #endregion } } diff --git a/src/Service.Tests/SqlTests/RestApiTests/Patch/MsSqlPatchApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Patch/MsSqlPatchApiTests.cs index df4a86926c..eb65ead650 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Patch/MsSqlPatchApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Patch/MsSqlPatchApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Patch @@ -130,16 +128,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MSSQL; await InitializeTestFixture(context); - // Setup REST Components - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Patch/MySqlPatchApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Patch/MySqlPatchApiTests.cs index 7901393ce0..93b4b06b06 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Patch/MySqlPatchApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Patch/MySqlPatchApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Patch @@ -199,15 +197,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MYSQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs index 7983dc70f8..7bd61c46a8 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Patch/PatchApiTestBase.cs @@ -40,7 +40,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PatchOne_Insert_Nulled_Test"), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -59,7 +58,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PatchOne_Update_Nulled_Test"), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK @@ -90,7 +88,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationUniqueCharactersEntity, sqlQuery: GetQuery(nameof(PatchOne_Insert_UniqueCharacters_Test)), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -120,7 +117,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integration_NonAutoGenPK_EntityName, sqlQuery: GetQuery(nameof(PatchOne_Insert_NonAutoGenPK_Test)), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -140,7 +136,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PatchOne_Insert_CompositeNonAutoGenPK_Test"), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -160,7 +155,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PatchOne_Insert_Empty_Test"), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -178,7 +172,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PatchOne_Insert_Default_Test"), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -198,7 +191,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationMappingEntity, sqlQuery: GetQuery("PatchOne_Insert_Mapping_Test"), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -225,7 +217,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationEntityName, sqlQuery: GetQuery(nameof(PatchOne_Update_Test)), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK @@ -241,7 +232,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _entityWithCompositePrimaryKey, sqlQuery: GetQuery("PatchOne_Update_Default_Test"), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK @@ -257,7 +247,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PatchOne_Update_CompositeNonAutoGenPK_Test"), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK @@ -274,7 +263,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PatchOne_Update_Empty_Test"), - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK @@ -302,7 +290,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationEntityName, sqlQuery: GetQuery(nameof(PatchOne_Update_IfMatchHeaders_Test)), - controller: _restController, operationType: Operation.UpsertIncremental, headers: new HeaderDictionary(headerDictionary), requestBody: requestBody, @@ -334,10 +321,9 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationEntityName, sqlQuery: null, - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Cannot perform INSERT and could not find {_integrationEntityName} with primary key to perform UPDATE on.", expectedStatusCode: HttpStatusCode.NotFound, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.EntityNotFound.ToString() @@ -364,10 +350,9 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integration_NonAutoGenPK_EntityName, sqlQuery: null, - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Cannot perform INSERT and could not find {_integration_NonAutoGenPK_EntityName} with primary key to perform UPDATE on.", expectedStatusCode: HttpStatusCode.NotFound, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.EntityNotFound.ToString() @@ -396,11 +381,10 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.UpsertIncremental, headers: new HeaderDictionary(headerDictionary), requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "No Update could be performed, record not found", expectedStatusCode: HttpStatusCode.PreconditionFailed, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.DatabaseOperationFailed.ToString() @@ -429,9 +413,8 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationBrokenMappingEntity, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.UpsertIncremental, - exception: true, + exceptionExpected: true, requestBody: requestBody, expectedErrorMessage: "Invalid request body. Either insufficient or extra fields supplied.", expectedStatusCode: HttpStatusCode.BadRequest, @@ -461,10 +444,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid value for field categoryName in request body.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -482,10 +464,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.UpsertIncremental, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid value for field categoryName in request body.", expectedStatusCode: HttpStatusCode.BadRequest ); diff --git a/src/Service.Tests/SqlTests/RestApiTests/Patch/PostgreSqlPatchApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Patch/PostgreSqlPatchApiTests.cs index 4868d8a995..8d75a30e1d 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Patch/PostgreSqlPatchApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Patch/PostgreSqlPatchApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Patch @@ -183,15 +181,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.POSTGRESQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } #endregion diff --git a/src/Service.Tests/SqlTests/RestApiTests/Put/MsSqlPutApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Put/MsSqlPutApiTests.cs index 8cc989f8a1..fbc42bb887 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Put/MsSqlPutApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Put/MsSqlPutApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Put @@ -173,16 +171,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MSSQL; await InitializeTestFixture(context); - // Setup REST Components - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Put/MySqlPutApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Put/MySqlPutApiTests.cs index 9265280687..5e7610c1ad 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Put/MySqlPutApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Put/MySqlPutApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Put @@ -258,15 +256,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.MYSQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } /// diff --git a/src/Service.Tests/SqlTests/RestApiTests/Put/PostgreSqlPutApiTests.cs b/src/Service.Tests/SqlTests/RestApiTests/Put/PostgreSqlPutApiTests.cs index 8376bc4533..5bc5f1da3b 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Put/PostgreSqlPutApiTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Put/PostgreSqlPutApiTests.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests.Put @@ -258,15 +256,6 @@ public static async Task SetupAsync(TestContext context) { DatabaseEngine = TestCategory.POSTGRESQL; await InitializeTestFixture(context); - _restService = new RestService(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - _restController = new RestController(_restService, - _restControllerLogger); } #endregion diff --git a/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs index 3f0c6a939d..7a8229b162 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/Put/PutApiTestBase.cs @@ -37,7 +37,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationEntityName, sqlQuery: GetQuery(nameof(PutOne_Update_Test)), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK @@ -54,7 +53,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _entityWithCompositePrimaryKey, sqlQuery: GetQuery("PutOne_Update_Default_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK, @@ -74,7 +72,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PutOne_Update_CompositeNonAutoGenPK_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK, @@ -95,7 +92,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PutOne_Update_NullOutMissingField_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK, @@ -115,7 +111,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PutOne_Update_Empty_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK, @@ -144,7 +139,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationEntityName, sqlQuery: GetQuery(nameof(PutOne_Update_IfMatchHeaders_Test)), - controller: _restController, operationType: Operation.Upsert, headers: new HeaderDictionary(headerDictionary), requestBody: requestBody, @@ -173,7 +167,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integration_NonAutoGenPK_EntityName, sqlQuery: GetQuery(nameof(PutOne_Insert_Test)), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -195,7 +188,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integration_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PutOne_Insert_Nullable_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -218,7 +210,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integration_AutoGenNonPK_EntityName, sqlQuery: GetQuery("PutOne_Insert_AutoGenNonPK_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -238,7 +229,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PutOne_Insert_CompositeNonAutoGenPK_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -256,7 +246,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PutOne_Insert_Default_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -276,7 +265,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PutOne_Insert_Empty_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -307,7 +295,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PutOne_Insert_Nulled_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.Created, @@ -329,7 +316,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: GetQuery("PutOne_Update_Nulled_Test"), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK, @@ -358,7 +344,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationMappingEntity, sqlQuery: GetQuery(nameof(PutOne_Update_With_Mapping_Test)), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK @@ -388,7 +373,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integrationEntityName, sqlQuery: GetQuery(query), - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedStatusCode: HttpStatusCode.OK @@ -414,10 +398,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request body. Missing field in body: categoryName.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: "BadRequest" @@ -440,10 +423,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: expectedErrorMessage, expectedStatusCode: HttpStatusCode.InternalServerError, expectedSubStatusCode: $"{DataApiBuilderException.SubStatusCodes.DatabaseOperationFailed}" @@ -469,10 +451,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid request body. Missing field in body: publisher_id.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString() @@ -500,10 +481,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Cannot perform INSERT and could not find {_integrationEntityName} with primary key to perform UPDATE on.", expectedStatusCode: HttpStatusCode.NotFound, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.EntityNotFound.ToString() @@ -523,10 +503,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _entityWithCompositePrimaryKey, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Cannot perform INSERT and could not find {_entityWithCompositePrimaryKey} with primary key to perform UPDATE on.", expectedStatusCode: HttpStatusCode.NotFound, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.EntityNotFound.ToString() @@ -552,10 +531,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Invalid request body. Missing field in body: publisher_id.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString() @@ -571,10 +549,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: $"Invalid request body. Missing field in body: categoryName.", expectedStatusCode: HttpStatusCode.BadRequest, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest.ToString() @@ -599,7 +576,6 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integration_AutoGenNonPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, expectedErrorMessage: @"Invalid request body. Either insufficient or extra fields supplied.", @@ -629,11 +605,10 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _integrationEntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, headers: new HeaderDictionary(headerDictionary), requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "No Update could be performed, record not found", expectedStatusCode: HttpStatusCode.PreconditionFailed, expectedSubStatusCode: DataApiBuilderException.SubStatusCodes.DatabaseOperationFailed.ToString() @@ -661,10 +636,9 @@ await SetupAndRunRestApiTest( queryString: null, entity: _integration_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Primary Key for UPSERT requests is required.", expectedStatusCode: HttpStatusCode.BadRequest, expectedLocationHeader: expectedLocationHeader @@ -692,10 +666,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid value for field categoryName in request body.", expectedStatusCode: HttpStatusCode.BadRequest ); @@ -713,10 +686,9 @@ await SetupAndRunRestApiTest( queryString: string.Empty, entity: _Composite_NonAutoGenPK_EntityName, sqlQuery: string.Empty, - controller: _restController, operationType: Operation.Upsert, requestBody: requestBody, - exception: true, + exceptionExpected: true, expectedErrorMessage: "Invalid value for field categoryName in request body.", expectedStatusCode: HttpStatusCode.BadRequest ); diff --git a/src/Service.Tests/SqlTests/RestApiTests/RestApiTestBase.cs b/src/Service.Tests/SqlTests/RestApiTests/RestApiTestBase.cs index 33ea346bc5..c9cc96725f 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/RestApiTestBase.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/RestApiTestBase.cs @@ -1,5 +1,3 @@ -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests @@ -10,8 +8,6 @@ namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestApiTests [TestClass] public abstract class RestApiTestBase : SqlTestBase { - protected static RestService _restService; - protected static RestController _restController; protected static readonly string _integrationEntityName = "Book"; protected static readonly string _integrationTableName = "books"; protected static readonly string _entityWithCompositePrimaryKey = "Review"; @@ -33,7 +29,7 @@ public abstract class RestApiTestBase : SqlTestBase protected static readonly string _integrationBrokenMappingEntity = "Fungus"; protected static readonly string _integrationUniqueCharactersEntity = "ArtOfWar"; protected static readonly string _integrationUniqueCharactersTable = "aow"; - protected static readonly string _nonExistentEntityName = "!@#$%^&*()_+definitely_nonexistent_entity!@#$%^&*()_+"; + protected static readonly string _nonExistentEntityName = "!@$%^&*()_+definitely_nonexistent_entity!@$%^&*()_+"; protected static readonly string _emptyTableEntityName = "Empty"; protected static readonly string _emptyTableTableName = "empty_table"; protected static readonly string _simple_all_books = "books_view_all"; diff --git a/src/Service.Tests/SqlTests/RestBootstrapTests/PrimaryKeyTestsForCompositeViews.cs b/src/Service.Tests/SqlTests/RestBootstrapTests/PrimaryKeyTestsForCompositeViews.cs index 68c4223cb0..c9c9adbc91 100644 --- a/src/Service.Tests/SqlTests/RestBootstrapTests/PrimaryKeyTestsForCompositeViews.cs +++ b/src/Service.Tests/SqlTests/RestBootstrapTests/PrimaryKeyTestsForCompositeViews.cs @@ -1,9 +1,7 @@ using System.Collections.Generic; using System.Net; using System.Threading.Tasks; -using Azure.DataApiBuilder.Service.Controllers; using Azure.DataApiBuilder.Service.Exceptions; -using Azure.DataApiBuilder.Service.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Azure.DataApiBuilder.Service.Tests.SqlTests.RestBootstrapTests @@ -106,17 +104,6 @@ await InitializeTestFixture( context: null, new List { compositeDbViewquery }, new List { customEntity }); - // Perform a GET operation on the view to confirm that it is functional. - // Set up rest controller. - RestService _restService = new(_queryEngine, - _mutationEngine, - _sqlMetadataProvider, - _httpContextAccessor.Object, - _authorizationService.Object, - _authorizationResolver, - _runtimeConfigProvider); - RestController _restController = new(_restService, - _restControllerLogger); // Query to validate the GET operation result. string query = @" @@ -133,8 +120,7 @@ await SetupAndRunRestApiTest( primaryKeyRoute: "book_id/1/author_id/123", queryString: string.Empty, entity: _compositeViewName, - sqlQuery: query, - controller: _restController + sqlQuery: query ); } } diff --git a/src/Service.Tests/SqlTests/SqlTestBase.cs b/src/Service.Tests/SqlTests/SqlTestBase.cs index fd637bd79b..3704375709 100644 --- a/src/Service.Tests/SqlTests/SqlTestBase.cs +++ b/src/Service.Tests/SqlTests/SqlTestBase.cs @@ -3,8 +3,8 @@ using System.IO; using System.Net; using System.Net.Http; +using System.Net.Http.Json; using System.Security.Claims; -using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Nodes; @@ -19,14 +19,12 @@ using Azure.DataApiBuilder.Service.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.Data.SqlClient; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Primitives; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using MySqlConnector; @@ -42,8 +40,6 @@ public abstract class SqlTestBase { protected static IQueryExecutor _queryExecutor; protected static IQueryBuilder _queryBuilder; - protected static IQueryEngine _queryEngine; - protected static IMutationEngine _mutationEngine; protected static Mock _authorizationService; protected static Mock _httpContextAccessor; protected static DbExceptionParser _dbExceptionParser; @@ -126,23 +122,6 @@ protected static async Task InitializeTestFixture(TestContext context, List() .WithWebHostBuilder(builder => { @@ -150,11 +129,21 @@ protected static async Task InitializeTestFixture(TestContext context, List(implementationFactory: (serviceProvider) => + { + return new SqlQueryEngine( + _queryExecutor, + _queryBuilder, + _sqlMetadataProvider, + ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider), + _authorizationResolver, + _queryEngineLogger + ); + }); services.AddSingleton(implementationFactory: (serviceProvider) => { return new SqlMutationEngine( - _queryEngine, + ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider), _queryExecutor, _queryBuilder, _sqlMetadataProvider, @@ -292,63 +281,6 @@ protected static async Task ResetDbStateAsync() using DbDataReader _ = await _queryExecutor.ExecuteQueryAsync(File.ReadAllText($"{DatabaseEngine}Books.sql"), parameters: null); } - /// - /// Constructs an http context with request consisting of the given query string and/or body data. - /// - /// query - /// The data to be put in the request body e.g. GraphQLQuery - /// The operation used to define the HttpContext HTTP Method - /// The http context with request consisting of the given query string (if any) - /// and request body (if any) as a stream of utf-8 bytes. - protected static DefaultHttpContext GetRequestHttpContext( - string queryStringUrl = null, - IHeaderDictionary headers = null, - string bodyData = null, - Operation operation = Operation.Read) - { - DefaultHttpContext httpContext; - IFeatureCollection features = new FeatureCollection(); - //Add response features - features.Set(new HttpResponseFeature()); - features.Set(new StreamResponseBodyFeature(new MemoryStream())); - - if (headers is not null) - { - features.Set(new HttpRequestFeature { Headers = headers, Method = SqlTestHelper.OperationTypeToHTTPVerb(operation) }); - httpContext = new(features); - } - else - { - features.Set(new HttpRequestFeature { Method = SqlTestHelper.OperationTypeToHTTPVerb(operation) }); - httpContext = new(features); - } - - if (!string.IsNullOrEmpty(queryStringUrl)) - { - httpContext.Request.QueryString = new(queryStringUrl); - } - - if (!string.IsNullOrEmpty(bodyData)) - { - MemoryStream stream = new(Encoding.UTF8.GetBytes(bodyData)); - httpContext.Request.Body = stream; - httpContext.Request.ContentLength = stream.Length; - } - - // Add identity object to the Mock context object. - ClaimsIdentity identity = new(authenticationType: "Bearer"); - identity.AddClaim(new Claim(ClaimTypes.Role, "anonymous")); - identity.AddClaim(new Claim(ClaimTypes.Role, "authenticated")); - - ClaimsPrincipal user = new(identity); - httpContext.User = user; - - // Set the user role as authenticated to allow tests to execute with all privileges. - httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER] = "authenticated"; - - return httpContext; - } - /// /// Sends raw SQL query to database engine to retrieve expected result in JSON format. /// @@ -406,10 +338,9 @@ protected static async Task GetDatabaseResultAsync( /// string represents the query string provided in URL /// string represents the name of the entity /// string represents the query to be executed - /// string represents the rest controller /// The operation type to be tested. /// string represents JSON data used in mutation operations - /// bool represents if we expect an exception + /// bool represents if we expect an exception /// string represents the error message in the JsonResponse /// int represents the returned http status code /// enum represents the returned sub status code @@ -420,12 +351,11 @@ protected static async Task SetupAndRunRestApiTest( string queryString, string entity, string sqlQuery, - RestController controller, Operation operationType = Operation.Read, string path = "api", IHeaderDictionary headers = null, string requestBody = null, - bool exception = false, + bool exceptionExpected = false, string expectedErrorMessage = "", HttpStatusCode expectedStatusCode = HttpStatusCode.OK, string expectedSubStatusCode = "BadRequest", @@ -435,27 +365,61 @@ protected static async Task SetupAndRunRestApiTest( int verifyNumRecords = -1, bool expectJson = true) { - ConfigureRestController( - controller, - queryString, - operationType, - headers, - requestBody - ); - string baseUrl = UriHelper.GetEncodedUrl(controller.HttpContext.Request); - if (expectedLocationHeader != null) + // Create the rest endpoint using the path and entity name. + string restEndPoint = path + "/" + entity; + + // Append primaryKeyRoute to the endpoint if it is not empty. + if (!string.IsNullOrEmpty(primaryKeyRoute)) + { + restEndPoint = restEndPoint + "/" + primaryKeyRoute; + } + + // Append queryString to the endpoint if it is not empty. + if (!string.IsNullOrEmpty(queryString)) { - expectedLocationHeader = - baseUrl - + @"/" + expectedLocationHeader; + restEndPoint = restEndPoint + queryString; } - IActionResult actionResult = await SqlTestHelper.PerformApiTest( - controller, - path, - entity, - primaryKeyRoute, - operationType); + // Use UnsafeRelaxedJsonEscaping to be less strict about what is encoded. + // For eg. Without using this encoder, quotation mark (") will be encoded as + // \u0022 rather than \". And single quote(') will be encoded as \u0027 rather + // than being left unescaped. + // More details can be found here: + // https://docs.microsoft.com/en-us/dotnet/api/system.text.encodings.web.javascriptencoder.unsaferelaxedjsonescaping?view=net-6.0 + JsonSerializerOptions options = new() + { + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + + // Get the httpMethod based on the operation to be executed. + HttpMethod httpMethod = SqlTestHelper.GetHttpMethodFromOperation(operationType); + + // Create the request to be sent to the engine. + HttpRequestMessage request; + if (!string.IsNullOrEmpty(requestBody)) + { + JsonElement requestBodyElement = JsonDocument.Parse(requestBody).RootElement.Clone(); + request = new(httpMethod, restEndPoint) + { + Content = JsonContent.Create(requestBodyElement, options: options) + }; + } + else + { + request = new(httpMethod, restEndPoint); + } + + // Add headers to the request if any. + if (headers is not null) + { + foreach ((string key, StringValues value) in headers) + { + request.Headers.Add(key, value.ToString()); + } + } + + // Send request to the engine. + HttpResponseMessage response = await HttpClient.SendAsync(request); // if an exception is expected we generate the correct error // The expected result should be a Query that confirms the result state @@ -468,18 +432,14 @@ operationType is Operation.Upsert || operationType is Operation.UpsertIncremental || operationType is Operation.Update || operationType is Operation.UpdateIncremental) - && actionResult is NoContentResult) + && response.StatusCode == HttpStatusCode.NoContent + ) { - expected = null; + expected = string.Empty; } else { - JsonSerializerOptions options = new() - { - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping - }; - - if (exception) + if (exceptionExpected) { expected = JsonSerializer.Serialize(RestController.ErrorResponse( expectedSubStatusCode.ToString(), @@ -489,33 +449,29 @@ operationType is Operation.Update || } else { + string baseUrl = HttpClient.BaseAddress.ToString() + path + "/" + entity; + if (!string.IsNullOrEmpty(queryString)) + { + baseUrl = baseUrl + "?" + HttpUtility.ParseQueryString(queryString).ToString(); + } + string dbResult = await GetDatabaseResultAsync(sqlQuery, expectJson); // For FIND requests, null result signifies an empty result set dbResult = (operationType is Operation.Read && dbResult is null) ? "[]" : dbResult; - expected = $"{{\"value\":{FormatExpectedValue(dbResult)}{ExpectedNextLinkIfAny(paginated, EncodeQueryString(baseUrl), $"{expectedAfterQueryString}")}}}"; + expected = $"{{\"{SqlTestHelper.jsonResultTopLevelKey}\":" + + $"{FormatExpectedValue(dbResult)}{ExpectedNextLinkIfAny(paginated, baseUrl, $"{expectedAfterQueryString}")}}}"; } } - SqlTestHelper.VerifyResult( - actionResult, - expected, - expectedStatusCode, - expectedLocationHeader, - !exception, - verifyNumRecords); - } - - /// - /// Helper function encodes the url with query string into the correct - /// format. We utilize the toString() of the HttpValueCollection - /// which is used by the NameValueCollection returned from - /// ParseQueryString to avoid writing this ourselves. - /// - /// Url to be encoded as query string. - /// query string encoded url. - private static string EncodeQueryString(string fullUrl) - { - return HttpUtility.ParseQueryString(fullUrl).ToString(); + // Verify the expected and actual response are identical. + await SqlTestHelper.VerifyResultAsync( + expected: expected, + request: request, + response: response, + exceptionExpected: exceptionExpected, + httpMethod: httpMethod, + expectedLocationHeader: expectedLocationHeader, + verifyNumRecords: verifyNumRecords); } /// @@ -541,34 +497,6 @@ private static string ExpectedNextLinkIfAny(bool paginated, string baseUrl, stri return paginated ? $",\"nextLink\":\"{baseUrl}{queryString}\"" : string.Empty; } - /// - /// Add HttpContext with query and body(if any) to the RestController - /// - /// The controller to configure. - /// The query string in the url. - /// The data to be put in the request body. - protected static void ConfigureRestController( - RestController restController, - string queryString, - Operation operation, - IHeaderDictionary headers = null, - string requestBody = null - ) - { - restController.ControllerContext.HttpContext = - GetRequestHttpContext( - queryString, - headers, - bodyData: requestBody, - operation); - - // Set the mock context accessor's request same as the controller's request. - _httpContextAccessor.Setup(x => x.HttpContext.Request).Returns(restController.ControllerContext.HttpContext.Request); - - //Set the mock context accessor's Items same as the controller's Items - _httpContextAccessor.Setup(x => x.HttpContext.Items).Returns(restController.ControllerContext.HttpContext.Items); - } - /// /// Read the data property of the GraphQLController result /// diff --git a/src/Service.Tests/SqlTests/SqlTestHelper.cs b/src/Service.Tests/SqlTests/SqlTestHelper.cs index ee10bb7661..fca6ea42fa 100644 --- a/src/Service.Tests/SqlTests/SqlTestHelper.cs +++ b/src/Service.Tests/SqlTests/SqlTestHelper.cs @@ -2,13 +2,12 @@ using System.Collections.Generic; using System.Linq; using System.Net; -using System.Text.Encodings.Web; +using System.Net.Http; using System.Text.Json; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Azure.DataApiBuilder.Config; -using Azure.DataApiBuilder.Service.Controllers; -using Azure.DataApiBuilder.Service.Models; -using Microsoft.AspNetCore.Mvc; +using Azure.DataApiBuilder.Service.Exceptions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; @@ -16,6 +15,9 @@ namespace Azure.DataApiBuilder.Service.Tests.SqlTests { public class SqlTestHelper : TestHelper { + // This is is the key which holds all the rows in the response + // for REST requests. + public static readonly string jsonResultTopLevelKey = "value"; public static void RemoveAllRelationshipBetweenEntities(RuntimeConfig runtimeConfig) { foreach ((string entityName, Entity entity) in runtimeConfig.Entities.ToList()) @@ -45,7 +47,8 @@ public static void RemoveAllRelationshipBetweenEntities(RuntimeConfig runtimeCon /// True if JSON objects are the same public static bool JsonStringsDeepEqual(string jsonString1, string jsonString2) { - return JToken.DeepEquals(JToken.Parse(jsonString1), JToken.Parse(jsonString2)); + return string.IsNullOrEmpty(jsonString1) && string.IsNullOrEmpty(jsonString2) || + JToken.DeepEquals(JToken.Parse(jsonString1), JToken.Parse(jsonString2)); } /// @@ -82,143 +85,91 @@ public static void TestForErrorInGraphQLResponse(string response, string message } } - /// - /// Performs test on the given entity name by calling the correct Api based on the - /// operation type passed for the given primaryKeyRoute (if any). - /// - /// The REST controller with the request context. - /// The entity name. - /// The primary key portion of the route. - /// The operation type to be tested. - public static async Task PerformApiTest( - RestController controller, - string path, - string entityName, - string primaryKeyRoute, - Operation operationType = Operation.Read) - - { - IActionResult actionResult; - string pathAndEntityName = $"{path}/{entityName}"; - switch (operationType) - { - case Operation.Read: - actionResult = await controller.Find($"{pathAndEntityName}/{primaryKeyRoute}"); - break; - case Operation.Insert: - actionResult = await controller.Insert($"{pathAndEntityName}"); - break; - case Operation.Delete: - actionResult = await controller.Delete($"{pathAndEntityName}/{primaryKeyRoute}"); - break; - case Operation.Update: - case Operation.Upsert: - actionResult = await controller.Upsert($"{pathAndEntityName}/{primaryKeyRoute}"); - break; - case Operation.UpdateIncremental: - case Operation.UpsertIncremental: - actionResult = await controller.UpsertIncremental($"{pathAndEntityName}/{primaryKeyRoute}"); - break; - default: - throw new NotSupportedException("This operation is not yet supported."); - } - - return actionResult; - } - /// /// Verifies the ActionResult is as expected with the expected status code. /// - /// The action result of the operation to verify. - /// string represents the expected result. This value can be null for NoContent or NotFound - /// results of operations like GET and DELETE - /// int represents the returned http status code + /// Expected result of the query execution. + /// The HttpRequestMessage sent to the engine via HttpClient. + /// The HttpResponseMessage returned by the engine. + /// Boolean value indicating whether an exception is expected as + /// a result of executing the request on the engine. + /// The http method specified in the request. /// The expected location header in the response(if any). - public static void VerifyResult( - IActionResult actionResult, + /// + /// + public static async Task VerifyResultAsync( string expected, - HttpStatusCode expectedStatusCode, + HttpRequestMessage request, + HttpResponseMessage response, + bool exceptionExpected, + HttpMethod httpMethod, string expectedLocationHeader, - bool isJson = false, - int verifyNumRecords = -1) + int verifyNumRecords) { - JsonSerializerOptions options = new() - { - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping - }; - string actual; - switch (actionResult) + string responseBody = await response.Content.ReadAsStringAsync(); + if (!exceptionExpected) { - case OkObjectResult okResult: - Assert.AreEqual((int)expectedStatusCode, okResult.StatusCode); - actual = JsonSerializer.Serialize(okResult.Value, options); - // if verifyNumRecords is positive we want to compare its value to - // the number of elements associated with "value" in the actual result. - // because the okResult.Value is an annonymous type we use the serialized - // json string, actual, to easily get the inner array and get its length. - if (verifyNumRecords >= 0) - { - Dictionary actualAsDict = JsonSerializer.Deserialize>(actual); - Assert.AreEqual(actualAsDict["value"].Length, verifyNumRecords); - } + // Assert that the expectedLocation and actualLocation are equal in case of + // POST operation. + if (httpMethod == HttpMethod.Post) + { + // Find the actual location using the response and request uri. + // Response uri = Request uri + "/" + actualLocation + // For eg. POST Request URI: http://localhost/api/Review + // 201 Created Response URI: http://localhost/api/Review/book_id/1/id/5001 + // therefore, actualLocation = book_id/1/id/5001 + string responseUri = (response.Headers.Location.OriginalString); + string requestUri = request.RequestUri.OriginalString; + string actualLocation = responseUri.Substring(requestUri.Length + 1); + Assert.AreEqual(expectedLocationHeader, actualLocation); + } - break; - case CreatedResult createdResult: - Assert.AreEqual((int)expectedStatusCode, createdResult.StatusCode); - Assert.AreEqual(expectedLocationHeader, createdResult.Location); - actual = JsonSerializer.Serialize(createdResult.Value); - break; - // NoContentResult does not have value property for messages - case NoContentResult noContentResult: - Assert.AreEqual((int)expectedStatusCode, noContentResult.StatusCode); - actual = null; - break; - case NotFoundResult notFoundResult: - Assert.AreEqual((int)expectedStatusCode, notFoundResult.StatusCode); - actual = null; - break; - default: - JsonResult actualResult = (JsonResult)actionResult; - actual = JsonSerializer.Serialize(actualResult.Value, options); - break; - } + // Assert the number of records received is equal to expected number of records. + if (response.StatusCode is HttpStatusCode.OK && verifyNumRecords >= 0) + { + Dictionary actualAsDict = JsonSerializer.Deserialize>(responseBody); + Assert.AreEqual(actualAsDict[jsonResultTopLevelKey].Length, verifyNumRecords); + } - Console.WriteLine($"Expected: {expected}\nActual: {actual}"); - if (isJson && !string.IsNullOrEmpty(expected)) - { - Assert.IsTrue(JsonStringsDeepEqual(expected, actual)); + Assert.IsTrue(JsonStringsDeepEqual(expected, responseBody)); } else { - Assert.AreEqual(expected, actual, ignoreCase: true); + // Quote(") has to be treated differently than other unicode characters + // as it has to be added with a preceding backslash. + responseBody = Regex.Replace(responseBody, @"\\u0022", @"\\"""); + + // Convert the escaped characters into their unescaped form. + responseBody = Regex.Unescape(responseBody); + Assert.AreEqual(expected, responseBody); } } /// - /// Returns the HTTP verb for a provided Operation. + /// Helper method to get the HttpMethod based on the operation type. /// - /// Operation such as Find, Upsert, Delete, etc. - /// When Operation.None is provided from some tests, return empty string. - /// Matching HttpConstants value - /// - public static string OperationTypeToHTTPVerb(Operation operationType) + /// The operation to be executed on the entity. + /// + /// + public static HttpMethod GetHttpMethodFromOperation(Operation operationType) { switch (operationType) { case Operation.Read: - return HttpConstants.GET; + return HttpMethod.Get; case Operation.Insert: - return HttpConstants.POST; + return HttpMethod.Post; + case Operation.Delete: + return HttpMethod.Delete; case Operation.Upsert: - return HttpConstants.PUT; + return HttpMethod.Put; case Operation.UpsertIncremental: - return HttpConstants.PATCH; - case Operation.Delete: - return HttpConstants.DELETE; - case Operation.None: - return string.Empty; + return HttpMethod.Patch; default: - throw new ArgumentException(message: $"Invalid operationType {operationType} provided"); + throw new DataApiBuilderException( + message: "Operation not supported for the request.", + statusCode: HttpStatusCode.BadRequest, + subStatusCode: DataApiBuilderException.SubStatusCodes.NotSupported); } } diff --git a/src/Service.Tests/TestHelper.cs b/src/Service.Tests/TestHelper.cs index 83609ab8a2..30d8c2ca7a 100644 --- a/src/Service.Tests/TestHelper.cs +++ b/src/Service.Tests/TestHelper.cs @@ -129,8 +129,12 @@ public static void AddMissingEntitiesToConfig(RuntimeConfig config, string entit ""permissions"": [ { ""role"": ""anonymous"", - ""actions"": [ ""read"" ] - }, + ""actions"": [" + + $" \"{Operation.Create.ToString().ToLower()}\"," + + $" \"{Operation.Read.ToString().ToLower()}\"," + + $" \"{Operation.Delete.ToString().ToLower()}\"," + + $" \"{Operation.Update.ToString().ToLower()}\" ]" + + @"}, { ""role"": ""authenticated"", ""actions"": [" + diff --git a/src/Service/Models/RestRequestContexts/RestRequestContext.cs b/src/Service/Models/RestRequestContexts/RestRequestContext.cs index b4de92e9b7..ffb734d6d6 100644 --- a/src/Service/Models/RestRequestContexts/RestRequestContext.cs +++ b/src/Service/Models/RestRequestContexts/RestRequestContext.cs @@ -157,9 +157,9 @@ public void CalculateCumulativeColumns() Console.Error.WriteLine(e.Message); Console.Error.WriteLine(e.StackTrace); throw new DataApiBuilderException( - message: "Request content invalid.", + message: "$filter query parameter is not well formed.", statusCode: HttpStatusCode.BadRequest, - subStatusCode: DataApiBuilderException.SubStatusCodes.AuthorizationCumulativeColumnCheckFailed); + subStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest); } } diff --git a/src/Service/dab-config.MsSql.json b/src/Service/dab-config.MsSql.json index 09e75a9c61..abb6d3c789 100644 --- a/src/Service/dab-config.MsSql.json +++ b/src/Service/dab-config.MsSql.json @@ -186,7 +186,7 @@ "permissions": [ { "role": "anonymous", - "actions": [ "read" ] + "actions": [ "create", "read", "update", "delete" ] }, { "role": "authenticated", @@ -478,7 +478,7 @@ "permissions": [ { "role": "anonymous", - "actions": [ "read" ] + "actions": [ "create", "read", "update" ] }, { "role": "authenticated", @@ -499,7 +499,7 @@ "permissions": [ { "role": "anonymous", - "actions": [ "read" ] + "actions": [ "create", "read", "update" ] }, { "role": "authenticated", @@ -645,6 +645,10 @@ "source": "empty_table", "rest": true, "permissions": [ + { + "role": "anonymous", + "actions": [ "read" ] + }, { "role": "authenticated", "actions": [ "create", "read", "update", "delete" ] @@ -817,6 +821,10 @@ "rest": true, "graphql": false, "permissions": [ + { + "role": "anonymous", + "actions": [ "read" ] + }, { "role": "authenticated", "actions": [ "*" ] @@ -831,6 +839,10 @@ "rest": true, "graphql": false, "permissions": [ + { + "role": "anonymous", + "actions": [ "read" ] + }, { "role": "authenticated", "actions": [ "*" ] diff --git a/src/Service/dab-config.MySql.json b/src/Service/dab-config.MySql.json index dc51f998da..ccd90e617f 100644 --- a/src/Service/dab-config.MySql.json +++ b/src/Service/dab-config.MySql.json @@ -183,7 +183,7 @@ "permissions": [ { "role": "anonymous", - "actions": [ "read" ] + "actions": [ "create", "read", "update", "delete" ] }, { "role": "authenticated", @@ -505,7 +505,7 @@ "permissions": [ { "role": "anonymous", - "actions": [ "read" ] + "actions": [ "create", "read", "update" ] }, { "role": "authenticated", @@ -526,7 +526,7 @@ "permissions": [ { "role": "anonymous", - "actions": [ "read" ] + "actions": [ "create", "read", "update" ] }, { "role": "authenticated", @@ -672,6 +672,10 @@ "source": "empty_table", "rest": true, "permissions": [ + { + "role": "anonymous", + "actions": [ "read" ] + }, { "role": "authenticated", "actions": [ "create", "read", "update", "delete" ] diff --git a/src/Service/dab-config.PostgreSql.json b/src/Service/dab-config.PostgreSql.json index 127e6ec26f..28718ca5fd 100644 --- a/src/Service/dab-config.PostgreSql.json +++ b/src/Service/dab-config.PostgreSql.json @@ -183,7 +183,7 @@ "permissions": [ { "role": "anonymous", - "actions": [ "read" ] + "actions": [ "create", "read", "update", "delete" ] }, { "role": "authenticated", @@ -505,7 +505,7 @@ "permissions": [ { "role": "anonymous", - "actions": [ "read" ] + "actions": [ "create", "read", "update" ] }, { "role": "authenticated", @@ -526,7 +526,7 @@ "permissions": [ { "role": "anonymous", - "actions": [ "read" ] + "actions": [ "create", "read", "update" ] }, { "role": "authenticated", @@ -672,6 +672,10 @@ "source": "empty_table", "rest": true, "permissions": [ + { + "role": "anonymous", + "actions": [ "read" ] + }, { "role": "authenticated", "actions": [ "create", "read", "update", "delete" ]