Search code examples
asp.netasp.net-mvc-3unit-testingeventsprotected

MVC custom filter, invoke ASP.NET pipeline event manually for unit test


public abstract class MyControllerBase : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext context)
    {
        // do some magic
    }
}

All of my controllers inherit from MyControllerBase. The problem is that now I can't unit test certain methods because the filter sets some authorisation/logic flags which influence code path.

Is there any way to manually trigger OnActionExecuting? How does the pipeline trigger these events?

EDIT: to show a little more the idea behind this design in response to comments. I basically have something like this:

public abstract class MyControllerBase : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext context)
    {
        UserProperties = 
             _userService
                .GetUserProperties(filterContext.HttpContext.User.Identity.Name);

        ViewBag.UserProperties = UserProperties;
    }

    public UserProperties { get; private set; }

    public bool CheckSomethingAboutUser()
    {
         return UserProperties != null 
            && UserProperties.IsAuthorisedToPerformThisAction;
    }

    // ... etc, other methods for querying UserProperties
}

So now anywhere in View or Controller I can get details of the current user, what is their email, what authorisation they have, which department they work for etc.

Example:

public class PurchasingController : MyControllerBase 
{
    public ActionResult RaisePurchaseOrder(Item item)
    {
        // can use UserProperties from base class to determine correct action...

        if (UserProperties.CanRaiseOrders)

        if (UserProperties.Department == item.AllocatedDepartment)
    }
}

So this design works really nice, but as you can see testing the above action is difficult as I can't directly manipulate the UserProperties in the test set up.


Solution

  • I'm not sure you're suppose to override OnActionExecuting like that in MCV, normally I make an ActionFilterAttribute

    public class SomeMagicAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
    
        }
    }
    

    Then your class:

    [SomeMagic]
    public abstract class MyControllerBase : Controller
    {
    
    }
    

    Then in your unit test you can just do

    var magic = new SomeMagicAttribute();
    var simulatedContext = new ActionExecutingContext();
    magic.OnActionExecuting(simulatedContext);