Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

OnActionExecuting and OnActionExecuted in MVC unit test

, 20 Jul 2013
Rate this:
Please Sign up or sign in to vote.
Here is a simple example of how to automatically call them when the main controller method is called.

When testing MVC controllers, OnActionExecuted and OnActionExecuting functions are not get called. Here is a simple example of how to automatically call them when the main controller method is called. All you have to do is wrap the controller call into the Invoke() function.

[TestClass]
public class MyTest
{
    [TestMethod]
    public void TestSomething()
    {
        var actionResult = Invoke(() => new MyController().DoSomething());      
    }

    protected static T Invoke<T>(Expression<Func<T>> exp) where T : ActionResult
    {
        var methodCall = (MethodCallExpression) exp.Body;
        var method = methodCall.Method;
        var memberExpression = (MemberExpression)methodCall.Object;

        Expression<Func<Object>> getCallerExpression = 
          Expression<Func<Object>>.Lambda<Func<Object>>(memberExpression);
        Func<Object> getCaller = getCallerExpression.Compile();
        var ctrlr = (Controller)getCaller();

        ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(ctrlr.GetType());
        ActionDescriptor actionDescriptor = 
          new ReflectedActionDescriptor(method, method.Name, controllerDescriptor);

        // OnActionExecuting

        var rc = new RequestContext();
        ctrlr.ControllerContext = new ControllerContext(rc, ctrlr);
        var ctx1 = new ActionExecutingContext(ctrlr.ControllerContext, 
          actionDescriptor, new Dictionary<string, object>());
        MethodInfo onActionExecuting = ctrlr.GetType().GetMethod(
          "OnActionExecuting", BindingFlags.Instance | BindingFlags.NonPublic);
        onActionExecuting.Invoke(ctrlr, new object[] { ctx1 });

        // call controller method

        T result = exp.Compile()();

        // OnActionExecuted

        var ctx2 = new ActionExecutedContext(ctrlr.ControllerContext, 
          actionDescriptor, false, null){Result = result};
        MethodInfo onActionExecuted = ctrlr.GetType().GetMethod(
          "OnActionExecuted", BindingFlags.Instance | BindingFlags.NonPublic);
        onActionExecuted.Invoke(ctrlr, new object[] { ctx2 });

        return (T)ctx2.Result;
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

m_kramar

Australia Australia
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 20 Jul 2013
Article Copyright 2013 by m_kramar
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid