There are many places in the code in the project I’m working on where HttpContext.Current.User is used to get id of the currently logged in user. This can be tricky when it comes to unit testing functions using the HttpContext.
One of the way to get around this is to mock the HttpContext by manually creating the identity. I would create a helper function which creates an identity, pass it in a new HttpContext and setthat new HttpContext to the current HTTP context. This function accepts an id for the current identity and a list of roles for that identity.
public static class HttpContextHelper { public static HttpContext SetCurrentContextIdentity(int currentPersonId, params string[] roles) { var identity = new GenericIdentity(string.Empty); identity.AddClaim( new Claim(ClaimTypes.NameIdentifier, currentPersonId.ToString(CultureInfo.InvariantCulture))); if (roles.Any()) { identity.AddClaims(roles.Select(x => new Claim(ClaimTypes.Role, x, ClaimValueTypes.String))); } var context = new HttpContext(new HttpRequest(@"C:\", "http://tempuri.org", null), new HttpResponse(null)) { User = new GenericPrincipal(identity, new string[0]) }; HttpContext.Current = context; return context; } }
In your tests or test setup where you need to mock the HttpContext, you can simply call the helper function
const int CurrentUserId = 1 HttpContextHelper.SetCurrentContextIdentity(CurrentUserId);
Better solution
I use the solution above only if HttpContext.Current.User is used all over the place and it’s infeasible to refactor. However, if you start your project from scratch or if you can refactor your code, the better solution is to use an interface and inject its implementation.
I would have an interface as below where I define two methods to get id and roles for current user.
public interface ICurrentUser { int PersonId(); IEnumerable<string> Roles(); }
Then create a class to implement this interface where it uses the current HttpContext to get the current user id and roles.
public class AdminCurrentUser : ICurrentUser { public int PersonId() => (int)HttpContext.Current.User.GetUserId(); public IEnumerable<string> Roles() => ((ClaimsIdentity)HttpContext.Current.User.Identity).ClaimType(ClaimTypes.Role).Select(x => x.Value); }
For the tests, you can mock ICurrentUser and tell it to return whatever value you want.
Emil Rasinski
Spot on with this write-up, I seriously feel this site needs a great deal more attention.
I’ll probably be returning to read through
more, thanks for the information!