Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I unit test my asp.net-mvc controller's OnActionExecuting method?

I've overridden my controller's OnActionExecuting method to set some internal state based on the executing filterContext. How do I test this? The method itself is protected so I assume I'll have to go higher up in the call stack.

What code do I need to test this?

I'm using mvc RC 1.

Edit: I'm also using nunit.

Thanks

like image 425
Dane O'Connor Avatar asked Feb 26 '09 18:02

Dane O'Connor


People also ask

How do you test a Action filter?

To unit test an action filter, you have to pass in an action filter context object (which requires a lot of setup). Action filter methods are void, so you have to verify the behavior by inspecting the context object (or dependencies, like a logger, if you are injecting those).

Which method is used in the unit testing application in .NET core?

Equal() method is a quick way to check whether an expected result is equal to a returned result. If they are equal, the test method will pass. Otherwise, the test will fail. There is also an Assert.


2 Answers

You need to add and use a Private Accessor. Right click in your controller class and choose Create Private Accessors from the menu and add them to your test project. Once in your test project, create your controller, then create an accessor for it. The method should be available on the accessor. Here's a sample test from my own code:

/// <summary>
///A test for OnActionExecuting
///</summary>
[TestMethod()]
[ExpectedException( typeof( InvalidOperationException ) )]
public void OnActionExecutingWindowsIdentityTest()
{
    var identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal( identity );
    var httpContext = MockRepository.GenerateStub<HttpContextBase>();
    httpContext.User = principal;

    var actionDescriptor = MockRepository.GenerateStub<ActionDescriptor>();

    RouteData routeData = new RouteData();

    BaseController controller = new BaseController();
    BaseController_Accessor accessor = new BaseController_Accessor( new PrivateObject( controller ) );
    ControllerContext controllerContext = MockRepository.GenerateStub<ControllerContext>( httpContext, routeData, controller );

    ActionExecutingContext filterContext = new ActionExecutingContext( controllerContext, actionDescriptor, new Dictionary<string, object>() );

    accessor.OnActionExecuting( filterContext );

}

EDIT: If you aren't using MSTest for your unit tests, you may have to generate the accessors by hand. Essentially, you make a wrapper class that exposes the private/protected methods of the class under test via equivalent public methods, pass an instance of the class under test to the wrapper, and then use reflection from the wrapper class to invoke the private/protected method on the class under test.

   public class MyClass
   {
       protected void DoSomething( int num )
       {
       }
   }

   public class MyClass_accessor
   {
       private MyClass privateObj;

       public MyClass_accessor( MyClass obj )
       {
           this.privateObj = obj;
       }

       public void DoSomething( int num )
       {
           MethodInfo info = privateObj.GetType()
                                       .GetMethod("DoSomething",
                                                   BindingFlags.NonPublic
                                                   | BindingFlags.Instance );

           info.Invoke(obj,new object[] { num });
       }
    }
like image 163
tvanfosson Avatar answered Oct 17 '22 10:10

tvanfosson


I recently had a similar problem and could not find satisfying solution. So I created my own helper function that invokes OnActionExecuted and OnActionExecuting. See code here http://mkramar.blogspot.com.au/2012/06/onactionexecuting-and-onactionexecuted.html

like image 36
m_kramar Avatar answered Oct 17 '22 08:10

m_kramar