I am trying to unit test my controller code which gets the information from the ClaimsPrincipal.Current. In the controller code I
public class HomeController {
public ActionResult GetName() {
return Content(ClaimsPrincipal.Current.FindFirst("name").Value);
}
}
And I am trying to mock my ClaimsPrincipal with claims but I still don't have any mock value from the claim.
// Arrange
IList<Claim> claimCollection = new List<Claim>
{
new Claim("name", "John Doe")
};
var identityMock = new Mock<ClaimsIdentity>();
identityMock.Setup(x => x.Claims).Returns(claimCollection);
var cp = new Mock<ClaimsPrincipal>();
cp.Setup(m => m.HasClaim(It.IsAny<string>(), It.IsAny<string>())).Returns(true);
cp.Setup(m => m.Identity).Returns(identityMock.Object);
var sut = new HomeController();
var contextMock = new Mock<HttpContextBase>();
contextMock.Setup(ctx => ctx.User).Returns(cp.Object);
var controllerContextMock = new Mock<ControllerContext>();
controllerContextMock.Setup(con => con.HttpContext).Returns(contextMock.Object);
controllerContextMock.Setup(con => con.HttpContext.User).Returns(cp.Object);
sut.ControllerContext = controllerContextMock.Object;
// Act
var viewresult = sut.GetName() as ContentResult;
// Assert
Assert.That(viewresult.Content, Is.EqualTo("John Doe"));
The viewresult.Content is empty as I run the unit test. Any help if I can add the mock claim. Thanks.
You don't need to mock
ClaimsPrincipal
it has not outside dependencies and you can created it un-mocked: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:
(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:
then your test shrinks down to:
and it now passes, I've just verified.