I am trying to unit test my code which includes the line:
UserLoginInfo userIdentity = UserManager.GetLogins(User.Identity.GetUserId()).FirstOrDefault();
I'm just stuck on one bit as I can't get:
User.Identity.GetUserId()
to return a value. I have been trying the following in the set-up of my controller:
var mock = new Mock<ControllerContext>();
mock.Setup(p => p.HttpContext.User.Identity.GetUserId()).Returns("string");
But it gives an error of "NotSupportedException was unhandled by user code". I have also tried the following:
ControllerContext controllerContext = new ControllerContext();
string username = "username";
string userid = Guid.NewGuid().ToString("N"); //could be a constant
List<Claim> claims = new List<Claim>{
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", username),
new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", userid)
};
var genericIdentity = new GenericIdentity("Andrew");
genericIdentity.AddClaims(claims);
var genericPrincipal = new GenericPrincipal(genericIdentity, new string[] { });
controllerContext.HttpContext.User = genericPrincipal;
Based on some code I found on stackoverflow, but this returns the same error "NotSupportedException was unhandled by user code".
Any help as to how I proceed would be appreciated. Thanks.
You can't set up the GetUserId method because it's an extension method. Instead you'll have to set up the name on the user's IIdentity property. GetUserId will use this to determine the UserId.
See this for more info: http://msdn.microsoft.com/en-us/library/microsoft.aspnet.identity.identityextensions.getuserid(v=vs.111).aspx
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 thatGetUserId()
depends onClaimsIdentity.FindFirstValue()
. As it turns out, that is also an extension method, but it depends onClaimsIdentity.FindFirst()
, which is markedvirtual
. Now we have our seam, so we can do the following:Update: I just realized that the solution I posted above only works for derived
ApiControllers
(as in, Web API). The MVCController
class doesn't have a settableUser
property. Fortunately it's pretty easy to go in through theController
'sControllerContext
to achieve the desired effect: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:Now instead of calling
User.Identity.GetUserId()
when you want the user's Id, you simply callGetUserId()
. When you need to mock out the user Id in tests, you simply do it like this: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.
This worked for me
using fakeiteasy
Now you can get values back from those IIdentity extention methods:
eg.
When viewing the GetUserId() method with ILSpy it shows
So GetUserId needs the Claim "nameidentifier"