在 ASP.NET WebApi 中测试路由配置 [英] Testing route configuration in ASP.NET WebApi

查看:18
本文介绍了在 ASP.NET WebApi 中测试路由配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对我的 WebApi 路由配置进行一些单元测试.我想测试路由 "/api/super" 是否映射到我的 SuperControllerGet() 方法.我已经设置了以下测试,但遇到了一些问题.

I am trying to do some unit testing of my WebApi route configuration. I want to test that the route "/api/super" maps to the Get() method of my SuperController. I've setup the below test and am having a few issues.

public void GetTest()
{
    var url = "~/api/super";

    var routeCollection = new HttpRouteCollection();
    routeCollection.MapHttpRoute("DefaultApi", "api/{controller}/");

    var httpConfig = new HttpConfiguration(routeCollection);
    var request = new HttpRequestMessage(HttpMethod.Get, url);

    // exception when url = "/api/super"
    // can get around w/ setting url = "http://localhost/api/super"
    var routeData = httpConfig.Routes.GetRouteData(request);
    request.Properties[HttpPropertyKeys.HttpRouteDataKey] = routeData;

    var controllerSelector = new DefaultHttpControllerSelector(httpConfig);

    var controlleDescriptor = controllerSelector.SelectController(request);

    var controllerContext =
        new HttpControllerContext(httpConfig, routeData, request);
    controllerContext.ControllerDescriptor = controlleDescriptor;

    var selector = new ApiControllerActionSelector();
    var actionDescriptor = selector.SelectAction(controllerContext);

    Assert.AreEqual(typeof(SuperController),
        controlleDescriptor.ControllerType);
    Assert.IsTrue(actionDescriptor.ActionName == "Get");
}

我的第一个问题是,如果我没有指定完全限定的 URL httpConfig.Routes.GetRouteData(request); 会抛出一个 InvalidOperationException 异常,并带有相对 URI 不支持此操作."

My first issue is that if I don't specify a fully qualified URL httpConfig.Routes.GetRouteData(request); throws a InvalidOperationException exception with a message of "This operation is not supported for a relative URI."

我的存根配置显然遗漏了一些东西.我更喜欢使用相对 URI,因为使用完全限定的 URI 进行路由测试似乎不合理.

I'm obviously missing something with my stubbed configuration. I would prefer to use a relative URI as it does not seem reasonable to use a fully qualified URI for route testing.

我上面的配置的第二个问题是我没有按照我的 RouteConfig 中的配置测试我的路由,而是使用:

My second issue with my configuration above is I am not testing my routes as configured in my RouteConfig but am instead using:

var routeCollection = new HttpRouteCollection();
routeCollection.MapHttpRoute("DefaultApi", "api/{controller}/");

如何使用在典型 Global.asax 中配置的分配的 RouteTable.Routes:

How do I make use of the assigned RouteTable.Routes as configured in a typical Global.asax:

public class MvcApplication : HttpApplication
{
    protected void Application_Start()
    {
        // other startup stuff

        RouteConfig.RegisterRoutes(RouteTable.Routes);
    }
}

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        // route configuration
    }
}

另外,我上面提到的可能不是最好的测试配置.如果有更精简的方法,我会全力以赴.

Further what I have stubbed out above may not be the best test configuration. If there is a more streamlined approach I am all ears.

推荐答案

我最近在测试我的 Web API 路由,这是我的方法.

I was recently testing my Web API routes, and here is how I did that.

  1. 首先,我创建了一个助手来将所有 Web API 路由逻辑移到那里:

    public static class WebApi
    {
        public static RouteInfo RouteRequest(HttpConfiguration config, HttpRequestMessage request)
        {
            // create context
            var controllerContext = new HttpControllerContext(config, Substitute.For<IHttpRouteData>(), request);

            // get route data
            var routeData = config.Routes.GetRouteData(request);
            RemoveOptionalRoutingParameters(routeData.Values);

            request.Properties[HttpPropertyKeys.HttpRouteDataKey] = routeData;
            controllerContext.RouteData = routeData;

            // get controller type
            var controllerDescriptor = new DefaultHttpControllerSelector(config).SelectController(request);
            controllerContext.ControllerDescriptor = controllerDescriptor;

            // get action name
            var actionMapping = new ApiControllerActionSelector().SelectAction(controllerContext);

            return new RouteInfo
            {
                Controller = controllerDescriptor.ControllerType,
                Action = actionMapping.ActionName
            };
        }

        private static void RemoveOptionalRoutingParameters(IDictionary<string, object> routeValues)
        {
            var optionalParams = routeValues
                .Where(x => x.Value == RouteParameter.Optional)
                .Select(x => x.Key)
                .ToList();

            foreach (var key in optionalParams)
            {
                routeValues.Remove(key);
            }
        }
    }

    public class RouteInfo
    {
        public Type Controller { get; set; }

        public string Action { get; set; }
    }

  1. 假设我有一个单独的类来注册 Web API 路由(默认情况下,它是在 Visual Studio ASP.NET MVC 4 Web 应用程序项目的 App_Start 文件夹中创建的):

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

  1. 我可以轻松测试我的路线:

    [Test]
    public void GET_api_products_by_id_Should_route_to_ProductsController_Get_method()
    {
        // setups
        var request = new HttpRequestMessage(HttpMethod.Get, "http://myshop.com/api/products/1");
        var config = new HttpConfiguration();

        // act
        WebApiConfig.Register(config);
        var route = WebApi.RouteRequest(config, request);

        // asserts
        route.Controller.Should().Be<ProductsController>();
        route.Action.Should().Be("Get");
    }

    [Test]
    public void GET_api_products_Should_route_to_ProductsController_GetAll_method()
    {
        // setups
        var request = new HttpRequestMessage(HttpMethod.Get, "http://myshop.com/api/products");
        var config = new HttpConfiguration();

        // act
        WebApiConfig.Register(config);
        var route = WebApi.RouteRequest(config, request);

        // asserts
        route.Controller.Should().Be<ProductsController>();
        route.Action.Should().Be("GetAll");
    }

    ....

以下注意事项:

  • 是的,我使用的是绝对网址.但我在这里没有看到任何问题,因为这些是假 URL,我不需要为它们配置任何东西,它们代表对我们网络服务的真实请求.
  • 您无需将路由映射代码复制到测试中,如果它们是在具有 HttpConfiguration 依赖项的单独类中配置的(如上例所示).
  • 我在上面的示例中使用了 NUnit、NSubstitute 和 FluentAssertions,但当然,使用任何其他测试框架也很容易.

这篇关于在 ASP.NET WebApi 中测试路由配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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