How do I mock User.Identity.GetUserId()?

You can’t mock extension methods directly, so your best bet is to drill down until you hit the properties and methods upon which the extension method depends that are mockable.

In this case, IIdentity.GetuUserId() is an extension method. I’d post it, but the library is not currently open source, so you’ll have to see for yourself that GetUserId() depends on ClaimsIdentity.FindFirstValue(). As it turns out, that is also an extension method, but it depends on ClaimsIdentity.FindFirst(), which is marked virtual. Now we have our seam, so we can do the following:

var claim = new Claim("test", "IdOfYourChoosing");
var mockIdentity =
    Mock.Of<ClaimsIdentity>(ci => ci.FindFirst(It.IsAny<string>()) == claim);
var controller = new MyController()
{
    User = Mock.Of<IPrincipal>(ip => ip.Identity == mockIdentity)
};

controller.User.Identity.GetUserId(); //returns "IdOfYourChoosing"

Update: I just realized that the solution I posted above only works for derived ApiControllers (as in, Web API). The MVC Controller class doesn’t have a settable User property. Fortunately it’s pretty easy to go in through the Controller‘s ControllerContext to achieve the desired effect:

var claim = new Claim("test", "IdOfYourChoosing");
var mockIdentity =
    Mock.Of<ClaimsIdentity>(ci => ci.FindFirst(It.IsAny<string>()) == claim);
var mockContext = Mock.Of<ControllerContext>(cc => cc.HttpContext.User == mockIdentity);
var controller = new MyController()
{
    ControllerContext = mockContext
};

However, if all you’re going to be using the User object for is to get the user’s Id, there’s another approach that will work for either type of controller and requires a lot less code:

public class MyController: Controller //or ApiController
{
    public Func<string> GetUserId; //For testing

    public MyController()
    {
        GetUserId = () => User.Identity.GetUserId();
    }
    //controller actions
}

Now instead of calling User.Identity.GetUserId() when you want the user’s Id, you simply call GetUserId(). When you need to mock out the user Id in tests, you simply do it like this:

controller = new MyController()
{
    GetUserId = () => "IdOfYourChoosing"
};

There are pros and cons to both approaches. The first approach is more thorough and more flexible and uses seams that are already present on the two controller types, but it’s also a lot more code and doesn’t read nearly as well. The second approach is much cleaner and IMO more expressive, but it is extra code to maintain, and if you don’t use the Func call to get the user’s Id, your tests won’t work. Choose whichever one works better for your situation.

Leave a Comment