【问题标题】:Unit Testing Custom Password Validators in ASP.NET Core在 ASP.NET Core 中对自定义密码验证器进行单元测试
【发布时间】:2017-12-26 21:50:21
【问题描述】:

我有一个覆盖 PasswordValidator 的 CustomPasswordValidator.cs 文件

 public class CustomPasswordValidator : PasswordValidator<AppUser>
    {   //override the PasswordValidator functionality with the custom definitions
        public override async Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager, AppUser user, string password)
        {
            IdentityResult result = await base.ValidateAsync(manager, user, password);

            List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();

            //check that the username is not in the password
            if (password.ToLower().Contains(user.UserName.ToLower()))
            {
                errors.Add(new IdentityError
                {
                    Code = "PasswordContainsUserName",
                    Description = "Password cannot contain username"
                });
            }

            //check that the password doesn't contain '12345'
            if (password.Contains("12345"))
            {
                errors.Add(new IdentityError
                {
                    Code = "PasswordContainsSequence",
                    Description = "Password cannot contain numeric sequence"
                });
            }
            //return Task.FromResult(errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray()));
            return errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray());
        }
    }

我是使用 Moq 和 xUnit 的新手。我正在尝试创建一个单元测试以确保产生正确数量的错误(显示工作代码,以及在 cmets 中产生错误的代码):

//test the ability to validate new passwords with Infrastructure/CustomPasswordValidator.cs 
        [Fact]
        public async void Validate_Password()
        {
            //Arrange
            <Mock><UserManager<AppUser>> userManager = new <Mock><UserManager<AppUser>>(); //caused null exception, use GetMockUserManager() instead
            <Mock><CustomPasswordValidator> customVal = new <Mock><CustomPasswordValidator>(); //caused null result object use customVal = new <CustomPasswordValidator>() instead
            <AppUser> user = new <AppUser>
            user.Name = "user" 
            //set the test password to get flagged by the custom validator
            string testPwd = "Thi$user12345";

            //Act
            //try to validate the user password
            IdentityResult result = await customVal.ValidateAsync(userManager, user, testPwd);

            //Assert
            //demonstrate that there are two errors present
            List<IdentityError> errors = result.Succeeded ? new List<IdentityError>() : result.Errors.ToList();
            Assert.Equal(errors.Count, 2);
        }

//create a mock UserManager class
        private Mock<UserManager<AppUser>> GetMockUserManager()
        {
            var userStoreMock = new Mock<IUserStore<AppUser>>();
            return new Mock<UserManager<AppUser>>(
                userStoreMock.Object, null, null, null, null, null, null, null, null);
        }

IdentityResult 行出现错误,表示我无法将 Mock 转换为 UserManager,也无法将 Mock 转换为 AppUser 类。

编辑:更改为包含在 ASP.NET 核心中模拟 UserManagerClass 所需的 GetMockUserManager() (Mocking new Microsoft Entity Framework Identity UserManager and RoleManager)

【问题讨论】:

    标签: c# asp.net unit-testing asp.net-core moq


    【解决方案1】:

    使用 Moq,您需要在模拟上调用 .Object 以获取模拟对象。您还应该使测试异步并等待被测方法。

    您还在模拟被测对象,在这种情况下,这会导致被测方法在调用时返回 null,因为它没有正确设置。此时您基本上是在测试模拟框架。

    创建被测对象CustomPasswordValidator 的实际实例并进行测试,模拟被测对象的显式依赖关系以获得所需的行为。

    public async Task Validate_Password() {
    
        //Arrange
        var userManagerMock = new GetMockUserManager();
        var subjetUnderTest = new CustomPasswordValidator();
        var user = new AppUser() {
            Name = "user" 
        }; 
        //set the test password to get flagged by the custom validator
        var password = "Thi$user12345";
    
        //Act
        IdentityResult result = await subjetUnderTest.ValidateAsync(userManagerMock.Object, user, password);
    
    
        //...code removed for brevity
    
    }
    

    阅读Moq Quickstart 以更熟悉如何使用起订量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-23
      • 2017-02-18
      • 1970-01-01
      • 2012-01-20
      • 2013-05-05
      • 2017-07-18
      • 1970-01-01
      • 2020-11-13
      相关资源
      最近更新 更多