Web Api将数据从Action Filter传递给Action,以便我可以进行单元测试

时间:2014-03-26 13:53:53

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

我有一个WebApi服务,需要对使用情况进行计费。这是一个WebApi v1 / MVC 4,我刚刚升级到WebApi 2 / MVC 5.我有一个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;
    ...
}

谢谢!

1 个答案:

答案 0 :(得分: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);