Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example of how to unit test a controller method which supports odata #438

Open
wants to merge 7 commits into
base: release-8.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions AspNetCoreOData.sln
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +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", "{2084B1F8-5122-41A1-8735-06F36E7C9903}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ODataAlternateKeySample", "sample\ODataAlternateKeySample\ODataAlternateKeySample.csproj", "{7B153669-A42F-4511-8BDB-587B3B27B2F3}"
EndProject
Global
Expand Down Expand Up @@ -65,6 +66,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
{7B153669-A42F-4511-8BDB-587B3B27B2F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7B153669-A42F-4511-8BDB-587B3B27B2F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B153669-A42F-4511-8BDB-587B3B27B2F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -82,6 +87,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}
{7B153669-A42F-4511-8BDB-587B3B27B2F3} = {B1F86961-6958-4617-ACA4-C231F95AE099}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Expand Down
88 changes: 88 additions & 0 deletions sample/ODataRoutingSample.Tests/AccountsControllerTests.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// This is a suggestion how to unit test a controller which will be very useful for the devs
/// </summary>
public class AccountsControllerTests
{
// It is not mocked because it is not used
private readonly ILogger<WeatherForecastController> _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>("Account");
var edmModel = modelBuilder.GetEdmModel();

var options = new ODataOptions();
options.AddRouteComponents("odata", EdmCoreModel.Instance);
options.AddRouteComponents("my{data}", edmModel);

HttpRequest request = RequestFactory.Create("GET",
"http://localhost/api?$top=2&$count=true",
dataOptions => dataOptions.AddRouteComponents("odata", edmModel));

var oDataQueryContext = new ODataQueryContext(edmModel, typeof(Account), new ODataPath());

var aDataQueryOptions = new ODataQueryOptions<Account>(oDataQueryContext, request);

// Act
_accountsController = new AccountsController(_mockedLogger);
var result = _accountsController.Get(aDataQueryOptions);
var accounts = (IQueryable<Account>) ((OkObjectResult) result).Value;

// Assert
Assert.Equal(2, accounts.Count());
}

[Fact]
public void AccountsController_SelectAccountWithNameEqualHot_ShouldReturnAccountWithHotName()
{
// Arrange
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Account>("Account");
var edmModel = modelBuilder.GetEdmModel();

var options = new ODataOptions();
options.AddRouteComponents("odata", EdmCoreModel.Instance);
options.AddRouteComponents("my{data}", edmModel);

HttpRequest request = RequestFactory.Create("GET",
"http://localhost/api?filter=Name eq 'Hot'",
dataOptions => dataOptions.AddRouteComponents("odata", edmModel));

var oDataQueryContext = new ODataQueryContext(edmModel, typeof(Account), new ODataPath());

var aDataQueryOptions = new ODataQueryOptions<Account>(oDataQueryContext, request);

// Act
_accountsController = new AccountsController(_mockedLogger);
var result = _accountsController.Get(aDataQueryOptions);
var accounts = (IQueryable<Account>)((OkObjectResult)result).Value;

// Assert
Assert.Equal("Hot", accounts.FirstOrDefault()?.Name);
}
}
}
22 changes: 22 additions & 0 deletions sample/ODataRoutingSample.Tests/ODataRoutingSample.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ODataRoutingSample\ODataRoutingSample.csproj" />
</ItemGroup>

</Project>
36 changes: 36 additions & 0 deletions sample/ODataRoutingSample.Tests/RequestFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.OData;
using Microsoft.Extensions.DependencyInjection;

namespace ODataRoutingSample
{
public static class RequestFactory
{
/// <summary>
/// Creates the <see cref="HttpRequest"/> with OData configuration.
/// </summary>
/// <param name="method">The http method.</param>
/// <param name="uri">The http request uri.</param>
/// <param name="setupDataConfigurationOption">Data configuration option action</param>
/// <returns>The HttpRequest.</returns>
public static HttpRequest Create(string method, string uri, Action<ODataOptions> setupDataConfigurationOption)
{
HttpContext context = new DefaultHttpContext();
HttpRequest request = context.Request;

IServiceCollection services = new ServiceCollection();
services.Configure(setupDataConfigurationOption);
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;
}
}
}