首页 > 解决方案 > 如何正确地向 HttpActionDescriptor ExecuteAsync 提供参数?

问题描述

我一直在关注Filip Wojcieszyn 的博客对我的路线进行单元测试。最近,我决定通过单元测试一个名为 IfNoneMatch 的自定义参数绑定属性来加强游戏。

长话短说,这里是控制器以及操作方法:

[RoutePrefix("api/etag")]
public class ETagController: ApiController
{
    [Route("getSingleStud/{id}")]
    public IHttpActionResult getStudent([IfNoneMatch]string etag, int id)
    {
        if (etag is null) return NotFound();
        else
            return Ok(new Student()
            {
                studId = id,
                firstName = "Phil",
                lastName = "Anderson",
                groupId = 1,
                group = null
            });
    }
}

按照博文代码,我实现了自己的方法来获取当前参数绑定属性。

public HttpParameterDescriptor GetParameterDescriptor()
    {
        if (controllerContext.ControllerDescriptor == null)
            GetControllerType();

        ApiControllerActionSelector actionSelector = new ApiControllerActionSelector();
        HttpActionDescriptor descriptor = actionSelector.SelectAction(controllerContext);

        return descriptor.GetParameters().Where(p => p.ParameterName == "etag").FirstOrDefault();
    }

我成功通过了以下测试:

[Fact]
    public void testParameterBinding()
    {
        //Arrange
        HttpConfiguration mockconfig = new HttpConfiguration();
        WebApiConfig.Register(mockconfig);
        mockconfig.EnsureInitialized();
        /*
            1. Somehow adding this piece of code fixed the uninitailized configuration issue
                https://stackoverflow.com/a/34325083
         */
        HttpRequestMessage mockRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44308/api/etag/1");

        RouteTester mockRouteTester = new RouteTester(mockconfig, mockRequestMessage);
        //Act
        HttpParameterDescriptor enumParamDescript = mockRouteTester.GetParameterDescriptor();
        //Assert
        Assert.True(enumParamDescript.ParameterBinderAttribute is IfNoneMatchAttribute);
    }

现在,问题是,正如您从控制器代码中看到的那样,ETag 可以为空,如果是这种情况,我将返回 404。显然,我想在选择正确的操作后立即测试这种行为。所以我检查了 HttpActionDescriptor 中暴露的 API 并找到了最接近的方法调用。

public abstract Task<object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary<string, object> arguments, CancellationToken cancellationToken);

查看此方法,我期望返回 HttpResponseMessage,我可以在其中检查 HttpStatusCode。以下是我对此的怀疑:

  1. 这是执行操作以检索 HttpResponseMessage 的正确方法吗?
  2. 我应该为 IDictionary 提供什么?

标签: asp.netunit-testingasp.net-web-api

解决方案


推荐阅读