【问题标题】:ASP.NET Core 6 - xUnit Test for Controller using custom IModelBinder to parse HttpRequest QueryASP.NET Core 6 - 使用自定义 IModelBinder 解析 HttpRequest 查询的控制器 xUnit 测试
【发布时间】:2022-08-03 17:13:12
【问题描述】:

我在测试解析查询字符串的自定义模型绑定器时有点迷失了。由于提供了 API,现在必须迁移到 .NET CORE,因此我无法更改 url 查询参数的语法。所以我不能使用[来自查询]控制器参数的属性。

控制器很简单:

public class HostListController
    : ControllerBase
    {
        [HttpGet]
        public async Task<ActionResult<IList<SomeDto>>> Get(
             CustomQueryExpr filter,
             [FromQuery] bool pretty)
        {
            // do some fetch
        }
    }

自定义模型绑定器的实现也很简单:

public class CustomQueryBinder
      : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            var parser = new QueryParser();
            //--- get queryString from request
            var queryString = bindingContext.HttpContext.Request.QueryString;

            //--- parse string  
            var queryExpr = parser.Parse(queryString.Value);

            bindingContext.Result = ModelBindingResult.Success(queryExpr);
            return Task.CompletedTask;
        }
    }

自定义的具体实现查询解析器不重要,它的方法\'Parse\'返回一个\'自定义查询表达式\' 无论如何都是实例。

现在我正在努力组装测试。

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;

public class TestCustomQueryBinder
    {
        [Fact]
        public async Task TestValidQuery_BindModel_ReturnCustomQueryExpr()
        {
            //--- assemble
            var modelMetadata = new EmptyModelMetadataProvider();

            var requestFake = new HttpRequestFeature();
            requestFake.QueryString = \"?filter_arg1=te*t&select=arg1,arg2\";

            var features = new FeatureCollection();
            features.Set<IHttpRequestFeature>(requestFake);

            var fakeHttpContext = new DefaultHttpContext(features);

            var bindingContext = new DefaultModelBindingContext
            {
                ModelName = \"CustomQueryExpr\",
                ModelMetadata = modelMetadata.GetMetadataForType(typeof(CustomQueryExpr)),
                ActionContext = new ActionContext()
                {
                    HttpContext = fakeHttpContext
                }
            };

            var binder = new CustomQueryBinder();

            //--- act
            await binder.BindModelAsync(bindingContext);

            //--- assert
            Assert.NotNull(bindingContext.Result);
            Assert.True(bindingContext.Result.IsModelSet);
            Assert.True(bindingContext.Result.Model is CustomQueryExpr);
        }
    }

现在按预期工作。有时它有助于简单地向他人解释问题以找出自己的错误......阿甘和树木。

但我确信这个解决方案可以改进,所以请添加你的 cmets、提示和改进来学习。谢谢!

  • 你对你的代码不满意吗?但在我看来,您的代码是一个非常常见的单元测试。 . .
  • 最初的问题是如何在 DefaultModelBindingContext 中设置 HttpContext,因为它是只读的。然后我想起了一种使用 ActionContext 解决问题的方法。所以我修复了描述/示例以显示解决方案。但最后 - 我猜,测试“知道”很多关于模型绑定器的实现。所以可能有更好的解决方案,我没有找到。

标签: c# unit-testing asp.net-core xunit custom-model-binder


【解决方案1】:

我有一个问题,关于自定义查询表达式

ModelMetadata = modelMetadata.GetMetadataForType(typeof(CustomQueryExpr))

因为当我尝试使用您的代码时,它给了我错误。 任何人都可以解释一下,如何定义和声明它。

【讨论】:

    猜你喜欢
    • 2017-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-16
    • 1970-01-01
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多