Asp.Net Core 2.1 ApiController不会在单元测试下自动验证模型 [英] Asp.Net Core 2.1 ApiController does not automatically validate model under unit test

查看:105
本文介绍了Asp.Net Core 2.1 ApiController不会在单元测试下自动验证模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用xUnit对返回ActionResult<T>的ASP.NET Core 2.1控制器方法进行单元测试.控制器类装饰有[ApiController]属性,以便该方法在实时运行时自动执行模型验证.但是,控制器方法不会在我的单元测试中自动触发模型验证,并且我不知道为什么.

I am using xUnit to unit test an ASP.NET Core 2.1 controller method that returns an ActionResult<T>. The controller class is decorated with the [ApiController] attribute so that the method, when running live, performs model validation automatically. However, the controller method does not automatically fire model validation in my unit test, and I can't figure out why.

这是我的单元测试.

[Fact]
public async Task post_returns_400_when_model_is_invalid()
{
    // arrange
    var mockHttpClientFactory = new Mock<IHttpClientFactory>();
    var mockHttpMessageHandler = new Mock<FakeHttpMessageHandler> {CallBase = true};
    mockHttpMessageHandler.Setup(mock => mock.Send(It.IsAny<HttpRequestMessage>()))
        .Returns(new HttpResponseMessage(HttpStatusCode.Accepted)
        {
            Content = new StringContent("{\"response\": {\"numFound\": 0, \"start\": 0, \"docs\": []}}")
        });
    var httpClient =
        new HttpClient(mockHttpMessageHandler.Object)
        {
            BaseAddress = new Uri("http://localhost:8983/"),
            DefaultRequestHeaders = {{"Accept", "application/json"}}
        };
    mockHttpClientFactory.Setup(mock => mock.CreateClient("SolrApi")).Returns(httpClient);
    var slackOptions = Options.Create<SlackOptions>(new SlackOptions());
    var prdSolrService = new PrdSolrService(Options.Create<PrdOptions>(new PrdOptions()));
    var slackMessageService = new PrdSlackMessageService(new HtmlTransformService(), slackOptions);
    var controller = new SlackPrdController(slackOptions, mockHttpClientFactory.Object, prdSolrService, slackMessageService);
    var slackRequest = new SlackRequest();

    // act
    var sut = await controller.Post(slackRequest);

    // assert 
    // note: validation should fail and not return a SlackMessage, but validation is not firing
    // auto-validation is part of [ApiController] attribute on the Controller class
    Assert.IsType<BadRequestObjectResult>(sut.Result);
}

这是正在测试的 Controller 方法.

[HttpPost]
public async Task<ActionResult<SlackMessage>> Post(SlackRequest request)
{
    if (request.Token != _slackOptions.Token)
    {
        ModelState.AddModelError("Token", "Invalid verification token.");
        return BadRequest(ModelState);
    }

    var solrUri = _solrService.SlackRequestToSolrUri(request);
    var client = _httpClientFactory.CreateClient("SolrApi");
    var raw = await client.GetStringAsync(solrUri);
    var response = _solrService.ParseSolrResponse(raw);
    var slackMessage = _slackMessageService.InitialMessage(response);

    return slackMessage;
}

这是 SlackRequest模型,其中需要Token属性.

Here is the SlackRequest model, where the Token property is required.

public class SlackRequest
{
    public SlackRequest() {}

    [JsonProperty("token")]
    [Required]
    public string Token { get; set; }

    [JsonProperty("team_id")]
    public string TeamId { get; set; }

    [JsonProperty("team_domain")]
    public string TeamDomain { get;set; }

    [JsonProperty("enterprise_id")]
    public string EnterpriseId { get; set; }

    [JsonProperty("enterprise_name")]
    public string EnterpriseName { get; set; }

    [JsonProperty("channel_id")]
    public string ChannelId { get; set; }

    [JsonProperty("channel_name")]
    public string ChannelName { get; set; }

    [JsonProperty("user_id")]
    public string UserId { get; set; }

    [JsonProperty("user_name")]
    public string UserName { get; set; }

    [JsonProperty("command")]
    public string Command { get;set; }

    [JsonProperty("text")]
    public string Text { get; set; }

    [Url]
    [JsonProperty("response_url")]
    public string ResponseUrl { get; set; }

    [JsonProperty("trigger_id")]
    public string TriggerId { get; set; }
}

推荐答案

控制器类装饰有[ApiController]属性,因此该方法在实时运行时会自动执行模型验证.但是,控制器方法不会在我的单元测试中自动触发模型验证,并且我不知道为什么.

The controller class is decorated with the [ApiController] attribute so that the method, when run live, performs model validation automatically. However, the controller method does not automatically fire model validation in my unit test, and I can't figure out why.

ApiControllerAttribute是仅在基础架构运行时才相关的元数据,因此这意味着您将必须在集成测试中使用TestServer并实际要求接受测试的操作才能使其成为测试的一部分并得到框架的认可.

The ApiControllerAttribute is metadata that is only relevant at run time by the infrastructure, so that means you will have to use TestServer in an integration test and actually request the action under test for it to be part of the test and recognized by the framework.

这是因为随着请求通过基础结构,该属性基本上标记了控制器/动作以进行动作过滤器(

This is because as the request goes through the infrastructure, the attribute basically tags the controller/action to let an action filter (ModelStateInvalidFilter) inspect the model and update the model state of the request. If model is found to be invalid it will short circuit the request so that is does not even reach the action to be invoked.

这篇关于Asp.Net Core 2.1 ApiController不会在单元测试下自动验证模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆