gpt4 book ai didi

unit-testing - 在 ASP.NET WebApi 中测试路由配置

转载 作者:行者123 更新时间:2023-12-03 07:26:57 27 4
gpt4 key购买 nike

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

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 不支持此操作。”

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

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

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

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

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
}
}

此外,我上面列出的可能不是最好的测试配置。如果有更精简的方法,我会洗耳恭听。

最佳答案

我最近正在测试我的 Web API 路由,以下是我的做法。

  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,我不需要配置任何内容即可让它们工作,并且它们代表对我们的 Web 服务的真实请求。
  • 如果路由映射代码是在具有 HttpConfiguration 依赖项的单独类中配置的(如上例所示),则无需将路由映射代码复制到测试中。
  • 我在上面的示例中使用了 NUnit、NSubstitute 和 FluentAssertions,但当然,使用任何其他测试框架执行相同的操作也是一项简单的任务。

关于unit-testing - 在 ASP.NET WebApi 中测试路由配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11851558/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com