I am trying to unit test my controller code which gets the information from the ClaimsPrincipal.Current. In the controller code I
public class HomeControlle
You don't need to mock ClaimsPrincipal
it has no outside dependencies and you can created it un-mocked:
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Name, "username"),
new Claim(ClaimTypes.NameIdentifier, "userId"),
new Claim("name", "John Doe"),
};
var identity = new ClaimsIdentity(claims, "TestAuthType");
var claimsPrincipal = new ClaimsPrincipal(identity);
And I'm not sure what you are testing here. Certainly "John Doe" will not be part of viewResult.Content
because it is never been set to this.
First, you are missing this line in your test:
Thread.CurrentPrincipal = cp.Object;
(and then cleaning it up in TearDown).
Second, as @trailmax mentioned, mocking principal objects is impractical. In your case, ClaimsPrincipal.FindFirst
(according to decompiled source) looks into private fields of its instance, that's the reason mocking didn't help.
I prefer using two simple classes that allow me to unit test claims-based functionality:
public class TestPrincipal : ClaimsPrincipal
{
public TestPrincipal(params Claim[] claims) : base(new TestIdentity(claims))
{
}
}
public class TestIdentity : ClaimsIdentity
{
public TestIdentity(params Claim[] claims) : base(claims)
{
}
}
then your test shrinks down to:
[Test]
public void TestGetName()
{
// Arrange
var sut = new HomeController();
Thread.CurrentPrincipal = new TestPrincipal(new Claim("name", "John Doe"));
// Act
var viewresult = sut.GetName() as ContentResult;
// Assert
Assert.That(viewresult.Content, Is.EqualTo("John Doe"));
}
and it now passes, I've just verified.