为.NET 5 Core控制器单元测试模拟或创建ODataQueryOptions

3
我正在将我们现有的API迁移到.NET 5,并且在单元测试迁移方面遇到了问题。 我想保留测试和测试控制器,但我无法找到处理ODataQueryOptions的方法,因为此类已经更改,我无法再创建ODataQueryOptions。 与我的问题相关的所有主题都已过时。
以下是迁移前控制器如何进行测试的旧代码。
_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);

如果有人能够提供处理类似问题的技巧并能够测试控制器,我将不胜感激。

2个回答

9

最终,我完成了这个任务。

为控制器编写单元测试的方法:

public PageResult<User> GetAll(ODataQueryOptions<User> odataQuery) 

单元测试

// 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);

您需要使用助手类来生成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;
        }

这是从这里获取的:https://github.com/OData/AspNetCoreOData/blob/master/test/Microsoft.AspNetCore.OData.Tests/Extensions/RequestFactory.cs

我希望它能帮助其他遇到相同问题的人。


2
我认为在当前版本中,“PrefixName”已更改为“RoutePrefix”,而“dataOptions.AddModel”已更改为“dataOptions.AddRouteComponents”。 - undefined
谢谢!我去过很多地方.... - undefined
这个按照Steve建议的变化,正如预期地工作。 - undefined

1
Galkin的回答适用于v8.x。我卡在Microsoft.AspNetCore.OData v7.7上,想出了以下解决方案(对我来说关键的部分是使用路由构建器调用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;
}

然后像这样创建ODataQueryOptions:
    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);

使用

    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; }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接