Reputation: 843
I am migration the our existing API to .net 5 and I face the issue of the unit tests migration. I want to keep tests and test controllers but I could not find a way hot to deal with ODataQueryOptions because this class has been change and I could not find a way to create a ODataQueryOptions any more. All topics which are related to my issue are outdated.
This is the old code how the controller has been tested before the migration
_userController.Request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://localhost/api?$orderby=UserName desc"));
_queryOptionsUser = new ODataQueryOptions<User>(_queryOptionsUser.Context, _userController.Request);
PageResult<UserDto> users = _userController.GetUsers(Constants.ValidOrgCode1, _queryOptionsUser);
I would be more than thankful if someone can provide the snipes how to deal with similar issue and be able to test a controller.
Upvotes: 3
Views: 2409
Reputation: 4711
Galkin's answer works for v8.x. I am stuck on Microsoft.AspNetCore.OData v7.7 and came up with this (critical part for me was having the route builder to call EnableDependencyInjection):
public static HttpRequest CreateHttpRequest(string uri)
{
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddOData();
IApplicationBuilder appBuilder = new ApplicationBuilder(serviceCollection.BuildServiceProvider());
IRouteBuilder routeBuilder = new RouteBuilder(appBuilder);
routeBuilder.EnableDependencyInjection();
HttpContext context = new DefaultHttpContext();
context.RequestServices = routeBuilder.ServiceProvider;
HttpRequest request = context.Request;
request.Method = "GET";
var requestUri = new Uri(uri);
request.Scheme = requestUri.Scheme;
request.Host = new HostString(requestUri.Host);
request.QueryString = new QueryString(requestUri.Query);
request.Path = new PathString(requestUri.AbsolutePath);
return request;
}
Then create ODataQueryOptions like this:
requestUri = "http://localhost/odata/foos/?$select=Id,Name";
var path = new Microsoft.AspNet.OData.Routing.ODataPath();
var model = CreateEdmModel<FooRow>("foos");
ODataQueryContext context = new ODataQueryContext(model, typeof(FooRow), path);
var request = CreateHttpRequest(requestUri);
var options = new ODataQueryOptions(context, request);
With
private static IEdmModel CreateEdmModel<TEntity>(string entitySetName) where TEntity : class
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<TEntity>(entitySetName);
return builder.GetEdmModel();
}
public class FooRow
{
public Guid Id { get; set; }
public string Name { get; set; }
}
Upvotes: 1
Reputation: 843
Finally, I ended doing this.
Have the method of the controller to unit test
public PageResult<User> GetAll(ODataQueryOptions<User> odataQuery)
Unit testing
// Arrange
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<User>("User");
var edmModel = modelBuilder.GetEdmModel();
const string routeName = "odata";
IEdmEntitySet entitySet = edmModel.EntityContainer.FindEntitySet("User");
ODataPath path = new ODataPath(new EntitySetSegment(entitySet));
var request = RequestFactory.Create("GET",
"http://localhost/api?$top=10&",
dataOptions => dataOptions.AddModel(routeName, edmModel));
request.ODataFeature().Model = edmModel;
request.ODataFeature().Path = path;
request.ODataFeature().PrefixName = routeName;
var oDataQueryContext = new ODataQueryContext(edmModel, typeof(User), new ODataPath());
var aDataQueryOptions = new ODataQueryOptions<User>(oDataQueryContext, request);
// Act
PageResult<User> users = _userController.GetAll(aDataQueryOptions);
You will need the helper class to generate HttpRequest
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="setupAction"></param>
/// <returns>The HttpRequest.</returns>
public static HttpRequest Create(string method, string uri, Action<ODataOptions> setupAction)
{
HttpContext context = new DefaultHttpContext();
HttpRequest request = context.Request;
IServiceCollection services = new ServiceCollection();
services.Configure(setupAction);
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;
}
it was taken from here https://github.com/OData/AspNetCoreOData/blob/master/test/Microsoft.AspNetCore.OData.Tests/Extensions/RequestFactory.cs
I hope it will help other who will face the same issue
Upvotes: 9