Reputation: 1152
I have a WebApi service that needs to bill usage. It's an WebApi v1 / MVC 4 that I just upgraded to WebApi 2 / MVC 5. I have an ActionFilterAttribute that will determine the pricing rules for the request. The ActionFilter adds the billing information to the HttpActionContext.Request.Properties. The controller action then performs service requested, bills the usage and returns results.
My problem is I now have a dependency on Request in my controller, which is causing me a problem in unit testing (Structuremap). I was hoping to create a class that exposed properties that internally accessed the Request object, so I could inject fake classes for testing. My first attempt is giving my problems.
I'm hoping to find a better way to pass data from to the controller that I could easily unit test. If I'm doing it the recommended way, then I'll try to solve the structuremap problems. Also, this is my first WebApi project, so I could be doing things the hard way.
Here's some code in case I missed critical details:
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;
...
}
Thanks!
Upvotes: 1
Views: 1357
Reputation: 19321
Your controller having dependency on Request
is not too bad. It is just a property and you can set it like this to any request object of your liking, as you you 'arrange' your test.
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);
Upvotes: 1