有没有一种简单的方法可以模拟IIdentity.GetUserId和IIdentity.IsAuthenticated?

我已经测试了这种方式,并得到了NotSupportedException。

[Test]
public void CanGetUserIdFromIdentityTest()
{
    //Enviroment
    var mockIdentity = new Mock<IIdentity>();
    mockIdentity.Setup(x => x.Name).Returns("[email protected]");
    mockIdentity.Setup(x => x.IsAuthenticated).Returns(true);
    mockIdentity.Setup(x => x.GetUserId()).Returns("12345");

    var mockPrincipal = new Mock<IPrincipal>();
    mockPrincipal.Setup(x => x.Identity).Returns(mockIdentity.Object);
    mockPrincipal.Setup(x => x.IsInRole(It.IsAny<string>())).Returns(true);

    //Action
    Kernel.Rebind<IPrincipal>().ToConstant(mockPrincipal.Object);

    //Asserts
    var principal = Kernel.Get<IPrincipal>();
    Assert.IsNotNull(principal.Identity.GetUserId());
    Assert.IsTrue(principal.Identity.IsAuthenticated);
}


我也使用GenericIdentity进行了测试。使用它,我可以模拟GetUserId(),但不能模拟IsAuthenticated属性。

有人可以帮助我吗?

最佳答案

您获得NotSupportedException,因为GetUserIdIdentityExtensions.GetUserId Method的扩展方法,并且不属于模拟对象。无需模拟GetUserId

如果您查看GetUserId的源代码,您会发现它不适用于您。

/// <summary>
///     Extensions making it easier to get the user name/user id claims off of an identity
/// </summary>
public static class IdentityExtensions
{
    /// <summary>
    ///     Return the user name using the UserNameClaimType
    /// </summary>
    /// <param name="identity"></param>
    /// <returns></returns>
    public static string GetUserName(this IIdentity identity)
    {
        if (identity == null)
        {
            throw new ArgumentNullException("identity");
        }
        var ci = identity as ClaimsIdentity;
        if (ci != null)
        {
            return ci.FindFirstValue(ClaimsIdentity.DefaultNameClaimType);
        }
        return null;
    }

    /// <summary>
    ///     Return the user id using the UserIdClaimType
    /// </summary>
    /// <param name="identity"></param>
    /// <returns></returns>
    public static string GetUserId(this IIdentity identity)
    {
        if (identity == null)
        {
            throw new ArgumentNullException("identity");
        }
        var ci = identity as ClaimsIdentity;
        if (ci != null)
        {
            return ci.FindFirstValue(ClaimTypes.NameIdentifier);
        }
        return null;
    }

    /// <summary>
    ///     Return the claim value for the first claim with the specified type if it exists, null otherwise
    /// </summary>
    /// <param name="identity"></param>
    /// <param name="claimType"></param>
    /// <returns></returns>
    public static string FindFirstValue(this ClaimsIdentity identity, string claimType)
    {
        if (identity == null)
        {
            throw new ArgumentNullException("identity");
        }
        var claim = identity.FindFirst(claimType);
        return claim != null ? claim.Value : null;
    }
}


它正在寻找带有ClaimsIdentityClaimTypes.NameIdentifier,这就是为什么它适用于GenericIdentity的原因。因此,这意味着您需要创建身份的存根。为了使IsAuthenticated工作,您只需要在构造函数中提供一个身份验证类型即可。空字符串将起作用。

这是您所做的更改的测试方法

[Test]
public void Should_GetUserId_From_Identity() {
    //Arrange
    var username = "[email protected]";
    var identity = new GenericIdentity(username, "");
    var nameIdentifierClaim = new Claim(ClaimTypes.NameIdentifier, username);
    identity.AddClaim(nameIdentifierClaim);

    var mockPrincipal = new Mock<IPrincipal>();
    mockPrincipal.Setup(x => x.Identity).Returns(identity);
    mockPrincipal.Setup(x => x.IsInRole(It.IsAny<string>())).Returns(true);

    Kernel.Rebind<IPrincipal>().ToConstant(mockPrincipal.Object);

    //Act
    var principal = Kernel.Get<IPrincipal>();

    //Asserts
    Assert.AreEqual(username, principal.Identity.GetUserId());
    Assert.IsTrue(principal.Identity.IsAuthenticated);
}

关于c# - 如何在没有ControllerContext的情况下从IIdentity模拟GetUserId和IsAuthenticated,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37264994/

10-12 05:51