【问题标题】:How do you stub User.Identity.GetUserId() in ASP MVC 5 (Microsoft.AspNet.Identity)你如何在 ASP MVC 5 (Microsoft.AspNet.Identity) 中存根 User.Identity.GetUserId()
【发布时间】:2016-10-06 22:52:01
【问题描述】:

如何在 ASP MVC 5 (Microsoft.AspNet.Identity) 中为 MVC5 控制器的单元测试存根 User.Identity.GetUserId()? GetUserId() 是一个扩展,所以我不能直接模拟它。我需要在测试前分配 ID。 看来您必须创建一个声明并将其分配给一个 GenericIdentity。但是对于单元测试来说,这似乎有很多事情要做。你知道任何替代方案吗?

【问题讨论】:

标签: unit-testing asp.net-mvc-5 asp.net-identity


【解决方案1】:

非常感谢您的想法。我正在使用 NSubstitute。我既没有 Microsoft Fakes,也没有 JustMock。所以我结束了直接向 GenericIdentity 填充声明,这样我就可以控制 UserId 的值:

string username = "username";
string userid = Guid.NewGuid().ToString("N"); //could be a constant

List<Claim> claims = new List<Claim>{
    new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", username), 
    new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", userid)
};
var genericIdentity = new GenericIdentity("");
genericIdentity.AddClaims(claims);
var genericPrincipal = new GenericPrincipal(genericIdentity, new string[] { "Asegurado" });
controllerContext.HttpContext.User = genericPrincipal;

【讨论】:

  • 能否请您分享工作样本以供大家参考。我也在同一条线上工作。
  • IsAuthenticated 仍然是假的,有什么解决办法吗?
【解决方案2】:

准备好承受痛苦了吗?

这在很大程度上取决于您使用的模拟框架。根据我的假设,您使用的是 Moq,那么您有点不走运,因为 Moq 在这方面做得不好。原因是 Moq 不能模拟扩展方法(实际上是 can 但你不想/不应该这样做:-))

如果您使用的是 JustMock 等其他模拟框架,那么您的使用范围可能会有所不同。根据this 的说法,该死的景象比接下来的要容易得多。

我发现的最简单的方法(仍然远非简单)是使用Microsoft Fakes

大部分新的身份信息都是使用扩展接口编写的。我一辈子都想不通为什么他们认为这是个好主意,但你来了。

这是你需要做的。

首先为Microsoft.AspNet.Identity 创建一个假程序集。您可以通过右键单击程序集并选择“添加假货程序集”来执行此操作。这基本上会遍历程序集并为在那里找到的所有内容创建垫片和存根。您想要做的是将电话打到GetUserId,.. 实际上这并不太难。

那么你必须定期模拟 ControllerContext,听起来你很熟悉。

我认为以下代码将满足您的需求 -

        using (var context = ShimsContext.Create())
        {
            Microsoft.AspNet.Identity.Fakes
                .ShimIdentityExtensions.GetUserIdIIdentity =
            (i) => "Mr. T";

            var fakeHttpContext = new Mock<HttpContextBase>();
            var fakeIdentity = new GenericIdentity("User");
            var principal = new GenericPrincipal(fakeIdentity, null);

            fakeHttpContext.Setup(t => t.User).Returns(principal);

            var controllerContext = new Mock<ControllerContext>();
            controllerContext.Setup(t => t.HttpContext)
                .Returns(fakeHttpContext.Object);

            var sut = new HomeController();
            sut.ControllerContext = controllerContext.Object;

            var result = sut.YourTestAction();
            Assert.True(result.WhatYouCareAbout);
        }

当然,不一定是T先生。

HTH

【讨论】:

    【解决方案3】:

    您可以创建从 MvcContrib.TestHelper.Fakes 中的对象继承的假主体和/或身份

    然后你可以这样做:

            using (var userManager = _userManagerFactory.CreateUserManager())
            {
                var userId = Guid.NewGuid().ToString();
                var result = userManager.CreateAsync(new IdentityUser() { Id = userId, UserName = "userName" }, "password").Result;
    
                Assert.IsTrue(result.Succeeded, "failed to create user through usermanager");
    
                var fakePrincipal = new FakePrincipal(new FakeClaimIdentity(userId, "userName"), new[] { "SomeRole" });
    
                Assert.IsTrue(fakePrincipal.Identity.IsAuthenticated, "fake user did not come back authenticated");
    
            }
    

    我用来制作虚假声明身份的类是这样的:

    using System.Collections.Generic;
    using System.Security.Claims;
    using MvcContrib.TestHelper.Fakes;
    
    namespace Tests.Unit.Fakes
    {
        public class FakeClaimIdentity : ClaimsIdentity
        {
    
            private readonly FakeIdentity _fakeIdentity;
    
    
            public FakeClaimIdentity(string id, string userName) : base(userName)
            {
                _fakeIdentity = new FakeIdentity(userName);
                base.AddClaims(new List<Claim>
                {
                    new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", userName),
                    new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", id)
                });
            }
    
            public override bool IsAuthenticated
            {
                get { return _fakeIdentity.IsAuthenticated; }
            }
    
            public override string Name
            {
                get { return _fakeIdentity.Name; }
            }
    
            public override string AuthenticationType
            {
                get
                {
                    return _fakeIdentity.AuthenticationType;
                }
            }
        }
    }
    

    这样也可以测试 IsAuthenticated 部分(如果您关心身份的有效性)。

    【讨论】:

      猜你喜欢
      • 2013-10-06
      • 1970-01-01
      • 1970-01-01
      • 2016-01-28
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      • 2015-10-01
      • 2014-10-10
      相关资源
      最近更新 更多