When testing ASP.NET Core controllers in application that uses Azure AD we need usually current user at least for some tests. As there is no authenticated user when unit testing, we need to create one by our own. This blog post shows how to create claims identity for ASP.NET Core unit tests.
To have Azure AD user available we have to create fake claims identity and fill it with claims that test expects. Then we create the instance of constructor and initiate controller and HTTP context. The latter one contains identity.
Consider the following controller action.
public IActionResult Index()
{
var name = User.Identity.Name;
// Do something with name
return View();
}
Test like this will probably fail with exception as there is no code that deals with current user identity.
[Fact]
public void SampleTest()
{
var controller = new HomeController();
controller.Index();
}
Let’s organize typical claims identity with some claims to controller.
[Fact]
public void SampleTest()
{
var user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, "SomeValueHere"),
new Claim(ClaimTypes.Name, "gunnar@somecompany.com")
// other required and custom claims
}), "TestAuthentication");
var controller = new HomeController();
controller.ControllerContext = new ControllerContext()
{
HttpContext = new DefaultHttpContext { User = user }
};
controller.Index();
}
Now we have fake claims identity available and our controller will use this. When running this test in Visual Studio we can see that controller has current user now.
It is also possible to use factory classes for identity. In this case we have one class for production and this returns the current identity controller has. Another class is for testing and this class creates and returns fake identity. As I don’t see much benefit on using factories with no additional value I suggest to go with directly created fake identity. Creating the identity can be moved to some helper method in test class if it is needed in multiple tests.
View Comments (9)
Hi, Gunnar, what do you think about injecting IPrincipal in the Index action method? When running your app you can use a custom model binder to automatically get IPrincipal passed into the action method but when testing you have the convenience of passing the User using the IPrincipal interface.
With unit tests we don't have any binders to use as binders and other things happening in HTTP request pipeline are the matter of integration tests. By example, if you decorate controller action with Authorize attribute then from tests you can still call the action without any identity available.
Hi Gunnar, maybe I was not completely clear, but the model binder it not for unit tests. The model binder is only a requirement when you run your app. My approach is based on this (https://www.hanselman.com/blog/IPrincipalUserModelBinderInASPNETMVCForEasierTesting.aspx) presented by Scott Hanselman.
Yes, this is also one way how to do it. But then you have additional class and additional configuration. I'm sort of lazy programmer and I prefer to keep things as small as possible as codebases tend to grow over time.
What is a little disturbing for me on Hanselman's solution is the fact that the need to fake the identity is on the testing side but it floats up to web application although there are other ways how to do it without leaking this need out from testing.
My common approach looks like yours, although, I found Hanselman’s approach interesting.
Thank you for sharing your thoughts.
Cheers! :)
Ho man, you are the one. Beautifully simple. Been searching the interwebs for something like this.
Thanks this helped me alot.