我有一个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;
...
}
谢谢!
答案 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);