简体   繁体   中英

How to Mock GetUserId and IsAuthenticated from IIdentity without ControllerContext

Is there a easy way to Mock IIdentity.GetUserId and IIdentity.IsAuthenticated?

I've tested this way and got a NotSupportedException .

[Test]
public void CanGetUserIdFromIdentityTest()
{
    //Enviroment
    var mockIdentity = new Mock<IIdentity>();
    mockIdentity.Setup(x => x.Name).Returns("test@test.com");
    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);
}

I've tested using GenericIdentity too. Using that i can mock GetUserId() , but i can't mock IsAuthenticated property.

Anyone can help me?

You get the NotSupportedException because GetUserId is an extension method from IdentityExtensions.GetUserId Method and does not belong to the mocked object. There is no need to mock GetUserId .

If you look at the source code for GetUserId you will see what it is not working for you.

/// <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;
    }
}

It is looking for a ClaimsIdentity with a ClaimTypes.NameIdentifier , which it why it worked for GenericIdentity . So that mean that you would need to create a stub of the Identity. In order to get IsAuthenticated to work you just need to provide an authentication Type in the constructor. An empty string will work.

Here is your test method with the changes

[Test]
public void Should_GetUserId_From_Identity() {
    //Arrange
    var username = "test@test.com";
    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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM