How can you unit test an Action Filter in ASP.NET Web Api?

后端 未结 6 1707
我寻月下人不归
我寻月下人不归 2020-12-22 22:43

I was looking to add an Action Filter to my service to handle adding link data to the response message. I have found that I need to mock HttpActionExecutedContext but it\'s

6条回答
  •  轮回少年
    2020-12-22 23:02

    Here's a working example from 2018 (.NET Framework 4.5.1). It uses an ExceptionFilterAttribute but it should be similar for other FilterAttributes.

    [Test]
    public void MyTest()
    {
        var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.google.com"));
        var response = new HttpResponseMessage();
    
        // This next line is necessary to avoid the following error
        // if you call `context.Request.CreateResponse(...)` inside the filter:
        // System.InvalidOperationException: The request does not have an associated configuration object or the provided configuration was null.
        // Discovered from https://stackoverflow.com/a/44447355/3312114
        request.SetConfiguration(new HttpConfiguration());
    
        var context = ContextUtil.GetActionExecutedContext(request, response);
    
        _myFilter.OnException(context); // Execute your methods
    
        Assert.AreEqual(HttpStatusCode.InternalServerError, context.Response.StatusCode); // Make your assertions
    }
    

    Then just copy the ContextUtil class into your test project somewhere. @thomasb's comment on @tugberk's answer suggests the latest code is on Codeplex. While that comment was in 2014 so there may even be later code, the 2014 code worked for me (in Jan 2018) while the original linked code did not. I've copied the later version below for convenience. Just drop this into a new file.

    internal static class ContextUtil
    {
        public static HttpControllerContext CreateControllerContext(HttpConfiguration configuration = null, IHttpController instance = null, IHttpRouteData routeData = null, HttpRequestMessage request = null)
        {
            HttpConfiguration config = configuration ?? new HttpConfiguration();
            IHttpRouteData route = routeData ?? new HttpRouteData(new HttpRoute());
            HttpRequestMessage req = request ?? new HttpRequestMessage();
            req.SetConfiguration(config);
            req.SetRouteData(route);
    
            HttpControllerContext context = new HttpControllerContext(config, route, req);
            if (instance != null)
            {
                context.Controller = instance;
            }
            context.ControllerDescriptor = CreateControllerDescriptor(config);
    
            return context;
        }
    
        public static HttpActionContext CreateActionContext(HttpControllerContext controllerContext = null, HttpActionDescriptor actionDescriptor = null)
        {
            HttpControllerContext context = controllerContext ?? ContextUtil.CreateControllerContext();
            HttpActionDescriptor descriptor = actionDescriptor ?? CreateActionDescriptor();
            descriptor.ControllerDescriptor = context.ControllerDescriptor;
            return new HttpActionContext(context, descriptor);
        }
    
        public static HttpActionContext GetHttpActionContext(HttpRequestMessage request)
        {
            HttpActionContext actionContext = CreateActionContext();
            actionContext.ControllerContext.Request = request;
            return actionContext;
        }
    
        public static HttpActionExecutedContext GetActionExecutedContext(HttpRequestMessage request, HttpResponseMessage response)
        {
            HttpActionContext actionContext = CreateActionContext();
            actionContext.ControllerContext.Request = request;
            HttpActionExecutedContext actionExecutedContext = new HttpActionExecutedContext(actionContext, null) { Response = response };
            return actionExecutedContext;
        }
    
        public static HttpControllerDescriptor CreateControllerDescriptor(HttpConfiguration config = null)
        {
            if (config == null)
            {
                config = new HttpConfiguration();
            }
            return new HttpControllerDescriptor() { Configuration = config, ControllerName = "FooController" };
        }
    
        public static HttpActionDescriptor CreateActionDescriptor()
        {
            var mock = new Mock() { CallBase = true };
            mock.SetupGet(d => d.ActionName).Returns("Bar");
            return mock.Object;
        }
    }
    

提交回复
热议问题