diff --git a/AspNetCoreOData.sln b/AspNetCoreOData.sln index e019d258e..3fa695aa6 100644 --- a/AspNetCoreOData.sln +++ b/AspNetCoreOData.sln @@ -25,6 +25,8 @@ 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", "{2084B1F8-5122-41A1-8735-06F36E7C9903}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -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 + {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 @@ -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} + {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 new file mode 100644 index 000000000..5cc9166aa --- /dev/null +++ b/sample/ODataRoutingSample.Tests/AccountsControllerTests.cs @@ -0,0 +1,88 @@ +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 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 + /// + public class AccountsControllerTests + { + // It is not mocked because it is not used + private readonly ILogger _mockedLogger = null; + private AccountsController _accountsController; + + public AccountsControllerTests() + { + _accountsController = new AccountsController(_mockedLogger); + } + + [Fact] + 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&$count=true", + 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(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 new file mode 100644 index 000000000..407604c30 --- /dev/null +++ b/sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj @@ -0,0 +1,26 @@ + + + + net5.0 + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + 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; + } + } +}