From 5c8b78816ebcbe920028fa5eddbb00b49036d8bd Mon Sep 17 00:00:00 2001 From: "agalkin@ott1-eng.internal" Date: Fri, 26 Mar 2021 10:27:38 -0400 Subject: [PATCH 1/2] Example of how to unit test a controller method which supports odata --- AspNetCoreOData.sln | 9 ++- .../AccountsControllerTests.cs | 62 +++++++++++++++++++ .../ODataRoutingSample.Tests.csproj | 20 ++++++ .../RequestFactory.cs | 35 +++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 sample/ODataRoutingSample.Tests/AccountsControllerTests.cs create mode 100644 sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj create mode 100644 sample/ODataRoutingSample.Tests/RequestFactory.cs diff --git a/AspNetCoreOData.sln b/AspNetCoreOData.sln index 742c44872..3936f6c57 100644 --- a/AspNetCoreOData.sln +++ b/AspNetCoreOData.sln @@ -23,7 +23,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ODataCustomizedSample", "sa EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ODataDynamicModel", "sample\ODataDynamicModel\ODataDynamicModel.csproj", "{CE04E38B-547F-46C0-ABE4-F981E3A1874F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ODataSampleCommon", "sample\ODataSampleCommon\ODataSampleCommon.csproj", "{647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ODataSampleCommon", "sample\ODataSampleCommon\ODataSampleCommon.csproj", "{647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ODataRoutingSample.Tests", "sample\ODataRoutingSample.Tests\ODataRoutingSample.Tests.csproj", "{CD0608D8-36D0-4E45-9355-A2040960ADC8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -63,6 +65,10 @@ Global {647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA}.Debug|Any CPU.Build.0 = Debug|Any CPU {647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA}.Release|Any CPU.ActiveCfg = Release|Any CPU {647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA}.Release|Any CPU.Build.0 = Release|Any CPU + {CD0608D8-36D0-4E45-9355-A2040960ADC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD0608D8-36D0-4E45-9355-A2040960ADC8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD0608D8-36D0-4E45-9355-A2040960ADC8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD0608D8-36D0-4E45-9355-A2040960ADC8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -76,6 +82,7 @@ Global {BDC5474B-9511-4CDF-83FE-376C7130F7F0} = {B1F86961-6958-4617-ACA4-C231F95AE099} {CE04E38B-547F-46C0-ABE4-F981E3A1874F} = {B1F86961-6958-4617-ACA4-C231F95AE099} {647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA} = {B1F86961-6958-4617-ACA4-C231F95AE099} + {CD0608D8-36D0-4E45-9355-A2040960ADC8} = {B1F86961-6958-4617-ACA4-C231F95AE099} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {540C9752-AAC0-49EA-BA60-78490C90FF86} diff --git a/sample/ODataRoutingSample.Tests/AccountsControllerTests.cs b/sample/ODataRoutingSample.Tests/AccountsControllerTests.cs new file mode 100644 index 000000000..9c45a0209 --- /dev/null +++ b/sample/ODataRoutingSample.Tests/AccountsControllerTests.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.OData; +using Microsoft.AspNetCore.OData.Query; +using Microsoft.Extensions.Logging; +using Microsoft.OData.Edm; +using Microsoft.OData.ModelBuilder; +using Microsoft.OData.UriParser; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ODataRoutingSample.Controllers; +using ODataRoutingSample.Models; + +namespace ODataRoutingSample.Tests +{ + /// + /// This is a suggestion how to unit test a controller which will be very useful for the devs + /// + [TestClass] + public class AccountsControllerTests + { + // It is not mocked because it is not used + private readonly ILogger _mockedLogger = null; + private AccountsController _accountsController; + + [TestInitialize] + public void TestInit() + { + _accountsController = new AccountsController(_mockedLogger); + } + + [TestMethod] + public void AccountsController_GetTopTwoAccounts_ShouldReturnTopTwoAccounts() + { + // Arrange + var modelBuilder = new ODataConventionModelBuilder(); + modelBuilder.EntitySet("Account"); + var edmModel = modelBuilder.GetEdmModel(); + + var options = new ODataOptions(); + options.AddModel("odata", EdmCoreModel.Instance); + options.AddModel("my{data}", edmModel); + + HttpRequest request = RequestFactory.Create("GET", + "http://localhost/api?$top=2&$inlinecount=allpages", + dataOptions => dataOptions.AddModel("odata", edmModel)); + + var oDataQueryContext = new ODataQueryContext(edmModel, typeof(Account), new ODataPath()); + + var aDataQueryOptions = new ODataQueryOptions(oDataQueryContext, request); + + // Act + _accountsController = new AccountsController(_mockedLogger); + var result = _accountsController.Get(aDataQueryOptions); + var accounts = (IQueryable) ((OkObjectResult) result).Value; + + // Assert + Assert.AreEqual(2, accounts.Count(), "Incorrect returned number of top query!"); + } + } +} diff --git a/sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj b/sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj new file mode 100644 index 000000000..f8b696661 --- /dev/null +++ b/sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj @@ -0,0 +1,20 @@ + + + + net5.0 + + false + + + + + + + + + + + + + + diff --git a/sample/ODataRoutingSample.Tests/RequestFactory.cs b/sample/ODataRoutingSample.Tests/RequestFactory.cs new file mode 100644 index 000000000..ecee5a648 --- /dev/null +++ b/sample/ODataRoutingSample.Tests/RequestFactory.cs @@ -0,0 +1,35 @@ +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.OData; +using Microsoft.Extensions.DependencyInjection; + +namespace ODataRoutingSample +{ + public static class RequestFactory + { + /// + /// Creates the with OData configuration. + /// + /// The http method. + /// The http request uri. + /// The HttpRequest. + public static HttpRequest Create(string method, string uri, Action setupActio) + { + HttpContext context = new DefaultHttpContext(); + HttpRequest request = context.Request; + + IServiceCollection services = new ServiceCollection(); + services.Configure(setupActio); + context.RequestServices = services.BuildServiceProvider(); + + request.Method = method; + var requestUri = new Uri(uri); + request.Scheme = requestUri.Scheme; + request.Host = requestUri.IsDefaultPort ? new HostString(requestUri.Host) : new HostString(requestUri.Host, requestUri.Port); + request.QueryString = new QueryString(requestUri.Query); + request.Path = new PathString(requestUri.AbsolutePath); + + return request; + } + } +} From a679422c6e0a3c457b723957094181d5d22af907 Mon Sep 17 00:00:00 2001 From: "agalkin@ott1-eng.internal" Date: Sat, 26 Jun 2021 20:24:48 -0400 Subject: [PATCH 2/2] Example of how to unit test a controller method which supports odata protocol --- AspNetCoreOData.sln | 12 +++--- .../AccountsControllerTests.cs | 42 +++++++++++++++---- .../ODataRoutingSample.Tests.csproj | 12 ++++-- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/AspNetCoreOData.sln b/AspNetCoreOData.sln index 3936f6c57..3fa695aa6 100644 --- a/AspNetCoreOData.sln +++ b/AspNetCoreOData.sln @@ -25,7 +25,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ODataDynamicModel", "sample EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ODataSampleCommon", "sample\ODataSampleCommon\ODataSampleCommon.csproj", "{647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ODataRoutingSample.Tests", "sample\ODataRoutingSample.Tests\ODataRoutingSample.Tests.csproj", "{CD0608D8-36D0-4E45-9355-A2040960ADC8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ODataRoutingSample.Tests", "sample\ODataRoutingSample.Tests\ODataRoutingSample.Tests.csproj", "{2084B1F8-5122-41A1-8735-06F36E7C9903}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -65,10 +65,10 @@ Global {647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA}.Debug|Any CPU.Build.0 = Debug|Any CPU {647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA}.Release|Any CPU.ActiveCfg = Release|Any CPU {647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA}.Release|Any CPU.Build.0 = Release|Any CPU - {CD0608D8-36D0-4E45-9355-A2040960ADC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CD0608D8-36D0-4E45-9355-A2040960ADC8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CD0608D8-36D0-4E45-9355-A2040960ADC8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CD0608D8-36D0-4E45-9355-A2040960ADC8}.Release|Any CPU.Build.0 = Release|Any CPU + {2084B1F8-5122-41A1-8735-06F36E7C9903}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2084B1F8-5122-41A1-8735-06F36E7C9903}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2084B1F8-5122-41A1-8735-06F36E7C9903}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2084B1F8-5122-41A1-8735-06F36E7C9903}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -82,7 +82,7 @@ Global {BDC5474B-9511-4CDF-83FE-376C7130F7F0} = {B1F86961-6958-4617-ACA4-C231F95AE099} {CE04E38B-547F-46C0-ABE4-F981E3A1874F} = {B1F86961-6958-4617-ACA4-C231F95AE099} {647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA} = {B1F86961-6958-4617-ACA4-C231F95AE099} - {CD0608D8-36D0-4E45-9355-A2040960ADC8} = {B1F86961-6958-4617-ACA4-C231F95AE099} + {2084B1F8-5122-41A1-8735-06F36E7C9903} = {B1F86961-6958-4617-ACA4-C231F95AE099} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {540C9752-AAC0-49EA-BA60-78490C90FF86} diff --git a/sample/ODataRoutingSample.Tests/AccountsControllerTests.cs b/sample/ODataRoutingSample.Tests/AccountsControllerTests.cs index 9c45a0209..5cc9166aa 100644 --- a/sample/ODataRoutingSample.Tests/AccountsControllerTests.cs +++ b/sample/ODataRoutingSample.Tests/AccountsControllerTests.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -8,29 +7,27 @@ using Microsoft.OData.Edm; using Microsoft.OData.ModelBuilder; using Microsoft.OData.UriParser; -using Microsoft.VisualStudio.TestTools.UnitTesting; using ODataRoutingSample.Controllers; using ODataRoutingSample.Models; +using Xunit; namespace ODataRoutingSample.Tests { /// /// This is a suggestion how to unit test a controller which will be very useful for the devs /// - [TestClass] public class AccountsControllerTests { // It is not mocked because it is not used private readonly ILogger _mockedLogger = null; private AccountsController _accountsController; - [TestInitialize] - public void TestInit() + public AccountsControllerTests() { _accountsController = new AccountsController(_mockedLogger); } - [TestMethod] + [Fact] public void AccountsController_GetTopTwoAccounts_ShouldReturnTopTwoAccounts() { // Arrange @@ -43,7 +40,7 @@ public void AccountsController_GetTopTwoAccounts_ShouldReturnTopTwoAccounts() options.AddModel("my{data}", edmModel); HttpRequest request = RequestFactory.Create("GET", - "http://localhost/api?$top=2&$inlinecount=allpages", + "http://localhost/api?$top=2&$count=true", dataOptions => dataOptions.AddModel("odata", edmModel)); var oDataQueryContext = new ODataQueryContext(edmModel, typeof(Account), new ODataPath()); @@ -56,7 +53,36 @@ public void AccountsController_GetTopTwoAccounts_ShouldReturnTopTwoAccounts() var accounts = (IQueryable) ((OkObjectResult) result).Value; // Assert - Assert.AreEqual(2, accounts.Count(), "Incorrect returned number of top query!"); + Assert.Equal(2, accounts.Count()); + } + + [Fact] + public void AccountsController_SelectAccountWithNameEqualHot_ShouldReturnAccountWithHotName() + { + // Arrange + var modelBuilder = new ODataConventionModelBuilder(); + modelBuilder.EntitySet("Account"); + var edmModel = modelBuilder.GetEdmModel(); + + var options = new ODataOptions(); + options.AddModel("odata", EdmCoreModel.Instance); + options.AddModel("my{data}", edmModel); + + HttpRequest request = RequestFactory.Create("GET", + "http://localhost/api?filter=Name eq 'Hot'", + dataOptions => dataOptions.AddModel("odata", edmModel)); + + var oDataQueryContext = new ODataQueryContext(edmModel, typeof(Account), new ODataPath()); + + var aDataQueryOptions = new ODataQueryOptions(oDataQueryContext, request); + + // Act + _accountsController = new AccountsController(_mockedLogger); + var result = _accountsController.Get(aDataQueryOptions); + var accounts = (IQueryable)((OkObjectResult)result).Value; + + // Assert + Assert.Equal("Hot", accounts.FirstOrDefault()?.Name); } } } diff --git a/sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj b/sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj index f8b696661..407604c30 100644 --- a/sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj +++ b/sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj @@ -8,9 +8,15 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all +