views:

189

answers:

1

I want to test the OnException, OnActionExecuted event of an MVC controller.

If I use mock like this:

        var httpContext = MockRepository.GenerateMock<HttpContextBase>();
        var request = MockRepository.GenerateMock<HttpRequestBase>();

        httpContext.Expect(c => c.Request).Return(request).Repeat.AtLeastOnce();
        request.Expect(r => r.IsAuthenticated ).Return(true).Repeat.AtLeastOnce();


        var controller = new MyController() ;

        controller.ControllerContext = new ControllerContext(httpContext,
                                                             new RouteData(),
                                                             controller);

        var result = controller.Execute() as ViewResult;

…the action method is executing, but the events are not invoked.

+4  A: 

This is one of the separation of concerns principles of MVC. When you're unit testing a method, you're testing the method itself independent of any filters applied to it. (And OnException() and OnActionExecuting() are really just glorified filters.)

If you want to test those other methods independently, you're free to do so. Normally the way you'd go about this is by calling the filters like so:

((IActionFilter)controller).OnActionExecuting(...)
((IExceptionFilter)controller).OnException(...)

You'll have to create context objects to pass to these methods. In the end, you have three unit tests: one for OnActionExecuting(), one for OnException(), and one for the actual method you're testing. The nice thing about this setup is that once you've unit tested the filters once, you don't have to worry about them any more for any other unit tests.

For example, if you have a Method1(), Method2(), and Method3(), you don't need to test each combination of method + filters. Simply have five unit tests: OnActionExecuting(), OnException(), Method1(), Method2(), and Method3(). This eliminates redundant testing and makes it easier to track down potential bugs in your code.

Levi