【问题标题】:WebApi Passing data from ActionFilter to Action so I can Unit TestWebApi 将数据从 ActionFilter 传递到 Action,以便我可以进行单元测试
【发布时间】:2014-03-27 00:26:54
【问题描述】:

我有一个 WebApi 服务需要对使用量进行计费。这是我刚刚升级到 WebApi 2 / MVC 5 的 WebApi v1 / MVC 4。我有一个 ActionFilterAttribute 将确定请求的定价规则。 ActionFilter 将计费信息添加到 HttpActionContext.Request.Properties。然后,控制器操作执行请求的服务,对使用情况进行计费并返回结果。

我的问题是我现在在我的控制器中依赖 Request,这导致我在单元测试(Structuremap)中出现问题。我希望创建一个暴露内部访问 Request 对象的属性的类,这样我就可以注入假类进行测试。我的第一次尝试是给出我的问题。

我希望找到一种更好的方法将数据从控制器传递到我可以轻松进行单元测试的控制器。如果我按照推荐的方式进行操作,那么我将尝试解决结构映射问题。另外,这是我的第一个 WebApi 项目,所以我可能会遇到困难。

以下是一些代码,以防我错过关键细节:

ActionFilterAttribute:

public override void OnActionExecuting(HttpActionContext actionContext)
{
   ...
   actionContext.Request.Properties.Add("PricingRule", pricingRule);
   actionContext.Request.Properties.Add("ServiceUsage", serviceUsage);
   actionContext.Request.Properties.Add("ServiceEndPoint", serviceEndPoint);

   // Record how long it took to for pricing code to execute.
   actionContext.Request.Headers.Add("PriceDuration", span.TotalMilliseconds.ToString(CultureInfo.InvariantCulture));
}

Controller:

public HttpResponseMessage GetServiceRequest([FromUri]string customerId, [FromUri]string apiKey)
{
    ....
    var priceDuration = Request.Headers.GetValues("PriceDuration").FirstOrDefault();
    object myObject;
    Request.Properties.TryGetValue("PricingRule", out myObject);
    var pricingRule = (PricingRule)myObject;
    ...
}

谢谢!

【问题讨论】:

    标签: c# asp.net-web-api


    【解决方案1】:

    您的控制器对Request 的依赖还不错。它只是一个属性,您可以在“安排”测试时将其设置为您喜欢的任何请求对象。

    var controller = new MyApiControllerClassToUnitTest();
    controller.Configuration = new HttpConfiguration();
    var route = controller.Configuration.Routes.MapHttpRoute(
                           name: "DefaultApi",
                              routeTemplate: "api/{controller}/{id}",
                               defaults: new { id = RouteParameter.Optional });
    var routeValues = new HttpRouteValueDictionary();
    routeValues.Add("controller", controllerPrefix);
    var routeData = new HttpRouteData(route, routeValues);
    
    controller.Request = new HttpRequestMessage(HttpMethod.GET, "http://someuri");
    controller.Request.Properties.Add(
                HttpPropertyKeys.HttpConfigurationKey, controller.Configuration);
    controller.Request.Properties.Add(HttpPropertyKeys.HttpRouteDataKey, routeData);
    

    【讨论】:

    • 好的,我可以在单元测试中这样做,然后在设置请求后调用操作。我也在重新思考我的逻辑的不同部分在哪里以及它们属于哪里。设置单元测试让我更难找到代码所在的位置。如果这行得通,我就不需要在请求中填充数据,因为它从身份验证到过滤器再到操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 2013-09-11
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    • 1970-01-01
    相关资源
    最近更新 更多