在 ASP.NET WebApi 中测试路由配置 [英] Testing route configuration in ASP.NET WebApi
问题描述
我正在尝试对我的 WebApi 路由配置进行一些单元测试.我想测试路由 "/api/super"
是否映射到我的 SuperController
的 Get()
方法.我已经设置了以下测试,但遇到了一些问题.
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.
- 首先,我创建了一个助手来将所有 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; }
}
- 假设我有一个单独的类来注册 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 }
);
}
}
- 我可以轻松测试我的路线:
[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屋!