c# - 在 ASP.NET Core 中模拟 User.Identity 以进行单元测试

标签 c# unit-testing asp.net-core-mvc xunit

<分区>

我正在努力为包含 User.Identity.Name 功能的操作方法实现单元测试。我遇到的方法失败了,因为他们建议写入的属性会抛出“只读”错误(例如写入 HttpContext 或 Controller User)

我有一个 Action 方法:

[Authorize]
        public async Task<ViewResult> EditProject(int projectId)
        {
            Project project = repository.Projects.FirstOrDefault(p => p.ProjectID == projectId);
            if (project != null)
            {
            //HOW DO I MOCK USER.IDENTITY.NAME FOR THIS PORTION?
                var user = await userManager.FindByNameAsync(User.Identity.Name); 
                bool owned = await checkIfUserOwnsItem(project.UserID, user);
                if (owned)
                {
                    return View(project);
                }
                else
                {
                    TempData["message"] = $"User is not authorized to view this item";
                }
             }
            return View("Index");
        }

如果我想对这个 action 方法进行单元测试,我该如何模拟 User.Identity 对象?

[Fact]
        public async Task Can_Edit_Project()
        {
            //Arrange
            var user = new AppUser() { UserName = "JohnDoe", Id = "1" };
            Mock<IRepository> mockRepo = new Mock<IRepository>();
            mockRepo.Setup(m => m.Projects).Returns(new Project[]
            {
                new Project {ProjectID = 1, Name = "P1", UserID = "1"},
                new Project {ProjectID = 2, Name = "P2", UserID = "1"},
                new Project {ProjectID = 3, Name = "P3", UserID = "1"},
            });
            Mock<ITempDataDictionary> tempData = new Mock<ITempDataDictionary>();
            Mock<UserManager<AppUser>> userMgr = GetMockUserManager();
            //Arrange
            ProjectController controller = new ProjectController(mockRepo.Object, userMgr.Object)
            {
                TempData = tempData.Object,
            };


           //HOW WOULD I MOCK THE USER.IDENTITY.NAME HERE?
           //The example below causes two errors:
           // 1) 'Invalid setup on a non-virtual (overridable in VB) member
           //mock => mock.HttpContext
           //and 2) HttpContext does not contain a definition for IsAuthenticated
           var mock = new Mock<ControllerContext>();
           mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(user.UserName);
          mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);

            //Act
            var viewResult = await controller.EditProject(2);
            Project result = viewResult.ViewData.Model as Project;

            //Assert
            Assert.Equal(2, result.ProjectID);
        }

编辑: 通过添加下面的代码取得一些进展。

var claims = new List<Claim>()
            {
                new Claim(ClaimTypes.Name, "John Doe"),
                new Claim(ClaimTypes.NameIdentifier, "1"),
                new Claim("name", "John Doe"),
            };
            var identity = new ClaimsIdentity(claims, "TestAuthType");
            var claimsPrincipal = new ClaimsPrincipal(identity);

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

            var mockHttpContext = new Mock<HttpContext>();
            mockHttpContext.Setup(m => m.User).Returns(claimsPrincipal);

现在 User.Identity.Name 设置正确,但下面的行仍然返回 user = null

var user = await userManager.FindByNameAsync(User.Identity.Name);

如何确保我模拟的 UserManager 可以返回模拟的登录用户?

最佳答案

通过 ControllerContext 设置你的假 User

var context = new ControllerContext
{
    HttpContext = new DefaultHttpContext
    {
        User = fakeUser
    }
};

// Then set it to controller before executing test
controller.ControllerContext = context;

关于c# - 在 ASP.NET Core 中模拟 User.Identity 以进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49330154/

相关文章:

c# - 如何更改我的应用程序 Tile Graphic

c# - 通过 Twilio 发送带有 url 的短信

c# - 从 javascript 调用 Razor

unit-testing - 你如何验证一个请求是用 axios-mock-adapter 发出的?

c# - 对 DropdownList 使用枚举 : Missing a using directive or assembly reference

asp.net-mvc - 仅在 mvc 6 中将值从 EditorTemplate 传递给其布局模板

c# - 客户端 HttpWebRequest : ArgumentNullException s

c# - VS 创建单元测试命令不适用于内部方法?

android - Powermock 提示在 2 个地方找到 default.properties 文件

c# - 使用 IUrlHelper 生成版本化 API 操作的 URL