Как мне выполнить модульное тестирование метода OnActionExecuting моего контроллера asp.net-mvc? - PullRequest
10 голосов
/ 26 февраля 2009

Я переопределил метод OnActionExecuting моего контроллера, чтобы установить некоторое внутреннее состояние на основе выполнения filterContext. Как мне это проверить? Сам метод защищен, поэтому я предполагаю, что мне придется подняться выше в стеке вызовов.

Какой код мне нужен, чтобы проверить это?

Я использую mvc RC 1.

Редактировать: я также использую nunit.

Спасибо

Ответы [ 3 ]

15 голосов
/ 26 февраля 2009

Вам необходимо добавить и использовать приватный аксессор. Щелкните правой кнопкой мыши по классу контроллера и выберите в меню Create Private Accessors и добавьте их в свой тестовый проект. Попав в тестовый проект, создайте свой контроллер, а затем создайте для него средство доступа. Метод должен быть доступен на методе доступа. Вот пример теста из моего собственного кода:

/// <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 );

}

РЕДАКТИРОВАТЬ : Если вы не используете MSTest для своих модульных тестов, возможно, вам придется генерировать средства доступа вручную. По сути, вы создаете класс-оболочку, который предоставляет закрытые / защищенные методы тестируемого класса через эквивалентные открытые методы, передаете экземпляр тестируемого класса в оболочку, а затем используете отражение от класса-оболочки для вызова частного / защищенного метод на тестируемом классе.

   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 });
       }
    }
4 голосов
/ 26 июня 2012

У меня недавно была похожая проблема, и я не мог найти удовлетворительное решение. Поэтому я создал свою собственную вспомогательную функцию, которая вызывает OnActionExecuted и OnActionExecuting. Смотрите код здесь http://mkramar.blogspot.com.au/2012/06/onactionexecuting-and-onactionexecuted.html

0 голосов
/ 30 декабря 2013

Я пытался сделать это, но на самом деле я хотел проверить результат пользовательского атрибута применительно к фактическому контроллеру . В нашем случае у нас был атрибут авторизации, который устанавливал свойства на контроллере, контроллер затем использовал свойства. Наш код выглядит примерно так:

// Create the controller to test
PortalController controller = new PortalController();
var method = typeof(PortalController);
var attribute = method.GetCustomAttributes(typeof(OrganizationContextFilter),true).Cast<OrganizationContextFilter>().SingleOrDefault();

// Set the controller Context with our fake objects on it
controller.ControllerContext = this.GetDefaultControllerMock(controller);

// Execute the Organization Context Filter
var actionDescriptor = new Mock<ActionDescriptor>();
var context = Mock.Get(actionDescriptor.Object);
context.Setup(s => s.ControllerDescriptor).Returns(new Mock<ControllerDescriptor>().Object);

// Use the current controller Context
ActionExecutingContext filterContext = new ActionExecutingContext( controller.ControllerContext, actionDescriptor.Object, new Dictionary<string, object>() );
attribute.OnActionExecuting(filterContext);

// We have to use this one, because it has the result of the Attribute execution
PortalController pc = filterContext.Controller as PortalController;
ActionResult result = pc.MethodToTest(); // Call the controller that had OnActionExecuting results

Преимущество этого заключается в том, что мы фактически выполняем пользовательский атрибут MVC на контроллере, который мы на самом деле тестируем. Это одновременно использует пользовательский код атрибута и тестирует контроллер в ситуации, которая больше похожа на «реальный мир».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...