views:

206

answers:

1

The mechanics of making this work aren't hard, but testing it is a little strange. The scenario is that I want to dump some basic user data into the view data based on the User property of a base controller (an IPrincipal object) so that the master page always has it. I need access to my IUserManager (a service class), which is provided by custom DI in a controller factory. Mocking the user is no problem for testing. However, the easiest way to achieve this for every action in the base controller is to do it by overriding the OnAuthorization method. The base class then looks like this:

public abstract class BaseController : Controller
{
    public BaseController(IUserManager userManager)
    {
        UserManager = userManager;
    }

    public IUserManager UserManager { get; private set; }

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        UserManager.SetupUserViewData(User, ViewData);
    }
}

The problem is that there's no way that I've been able to figure in a test to get the OnAuth method to fire. I'd like to verify in my mock UserManager that the SetupUserViewData gets called. I'm not using a custom filter because I don't have a full-blown dependency injection framework in place (the filter would need to get an IUserManager).

Any suggestions? As this will be used everywhere, I'd like to get the testing right.

+2  A: 

You can do this by creating a class that inherits from your base controller with a public method that calls your OnAuthorization method. Something like this:

public class TestController : BaseController {
    public TestController(IUserManager userManager) : base(userManager) {
    }

    public void CallOnAuthorization(AuthorizationContext filterContext) {
        OnAuthorization(filterContext);
    }
}

Then you test it something like this:

[Test]
public void TestMethod() {
    var userManager = //Mock usermanager;
    var filterContext = //Mock AuthorizationContext;
    var controller = new TestController(userManager);
    controller.CallOnAuthorization(filterContext);
    //Assert here
}
Mattias Jakobsson
Do you think I'm testing the right thing then? I suppose I might be acting too academic here, but it feels weird because I'm assuming that the controller will execute correctly at runtime and call that method if there's an authorized user.
Jeff Putz
Well, if you were to test what I think you want you would test the framework, not your code. You have to assume that the framework you are using is already properly tested.
Mattias Jakobsson
BTW - You can test the OnAuthorization() method itself more easily by casting your controller to an IAuthorizationFilter and calling the OnAuthorization() method directly. (Note that Controller implements IAuthorizationFilter, and this interface delegates to your overridden method.)
Levi
@Levi Yes, you can. But in this example you still need to use a controller that inherits from BaseController (as it is abstract). And I would prefer to use a dedicated test controller then one of the production controllers. But you could remove the CallOnAuthorization() method from TestController in my example and cast the testcontroller if you want to.
Mattias Jakobsson
Thanks, guys. This was the solution I was already looking at, but I didn't want to "poison" the question by creating a preconceived answer. Thanks for the validation. Good call, Levi, on the cast too, I never made the connection.
Jeff Putz