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

前端 未结 3 1151
不思量自难忘°
不思量自难忘° 2021-02-08 10:49

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

3条回答
  •  执念已碎
    2021-02-08 11:15

    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:

    /// 
    ///A test for OnActionExecuting
    ///
    [TestMethod()]
    [ExpectedException( typeof( InvalidOperationException ) )]
    public void OnActionExecutingWindowsIdentityTest()
    {
        var identity = WindowsIdentity.GetCurrent();
        WindowsPrincipal principal = new WindowsPrincipal( identity );
        var httpContext = MockRepository.GenerateStub();
        httpContext.User = principal;
    
        var actionDescriptor = MockRepository.GenerateStub();
    
        RouteData routeData = new RouteData();
    
        BaseController controller = new BaseController();
        BaseController_Accessor accessor = new BaseController_Accessor( new PrivateObject( controller ) );
        ControllerContext controllerContext = MockRepository.GenerateStub( httpContext, routeData, controller );
    
        ActionExecutingContext filterContext = new ActionExecutingContext( controllerContext, actionDescriptor, new Dictionary() );
    
        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 });
           }
        }
    

提交回复
热议问题