本文介绍了如何在模拟 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)
        {
        }
    }

然后你的测试缩小到:

    [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 中添加声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-25 04:34