如何在模拟ClaimsPrincipal中添加索赔 [英] How to add claims in a mock ClaimsPrincipal
问题描述
我正在尝试对我的控制器代码进行单元测试,该代码从ClaimsPrincipal.Current获取信息. 在控制器代码中
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);
}
}
我正在尝试用索赔来模拟我的ClaimsPrincipal,但是从索赔中我仍然没有任何模拟值.
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"));
当我运行单元测试时,viewresult.Content为空.如果可以添加模拟声明,则有任何帮助.谢谢.
The viewresult.Content is empty as I run the unit test. Any help if I can add the mock claim. Thanks.
推荐答案
首先,您在测试中缺少此行:
First, you are missing this line in your test:
Thread.CurrentPrincipal = cp.Object;
(然后在TearDown中清理它).
(and then cleaning it up in TearDown).
其次,如@trailmax所述,模拟主体对象是不切实际的.在您的情况下,ClaimsPrincipal.FindFirst
(根据反编译的源代码)会查看其实例的私有字段,这就是模拟无济于事的原因.
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.
这篇关于如何在模拟ClaimsPrincipal中添加索赔的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!