【发布时间】: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