如何测试Asp.net会员资格?

cho*_*bo2 15 .net c# asp.net-mvc nunit unit-testing

我是单元测试的新手,我正在尝试测试我写的一些.NET会员资料.

所以我试图检查我的VerifyUser方法,检查用户凭据是否有效.

所以这就是它的样子:

public bool VerifyUser(string userName, string password)
    {
        bool valid = Membership.ValidateUser(userName, password);
        return valid;
    }
Run Code Online (Sandbox Code Playgroud)

现在,每次我运行单元测试时都会失败.我知道我正在传递正确的凭据和内容.然后我突然意识到,也许我的测试项目(与我的真实项目在同一个解决方案下)可能需要自己的web.config文件,其中包含连接字符串和内容.或者应用程序配置文件,因为它是一个应用程序库项目.

那么我只是web.config从我的真实项目中复制文件并将其称为一天?或者我应该只从中取出零件?或者我离开了.

我的数据库正在使用自定义数据库,其.net成员资格与我的数据库合并.所以在我的配置文件中,我必须指定一个ManagerProvider和一个roleProvider.

这就是我的单元测试的样子

   [Test]
   public void TestVerifyUser()
   {
      AuthenticateUser authenitcate = new AuthenticateUser();
      bool vaild = authenitcate.VerifyUser("chobo3", "1234567");


      Assert.That(vaild, Is.True);
   }
Run Code Online (Sandbox Code Playgroud)

后来我在我的一个asp.net mvc ActionResult方法(准确的登录视图)我有这个:

FormsAuthentication.RedirectFromLoginPage(loginValidation.UserName,rememberMe);

那么现在我该如何编写一个能够完成用户操作的单元测试.假设他们从主页开始,然后单击登录页面并成功登录.我希望他们重定向到主页.

我不知道如何在代码中表示.我很确定这些RedirectFromLoginPage作品和那些我现在正在测试的东西.我正在测试我在登录ActionResult方法中可能发生的3件事情.

  1. 用户登录并将其发送回来.
  2. 用户无法登录并被发送回LoginView并看到错误消息.
  3. 用户已尝试转到安全状态,并已重定向到登录页面.如果登录成功,将通过ReturnUrl重定向回安全页面.

所以我想做一个测试,看看它们是否正常工作.这就是为什么我需要让用户来自主页,看看他们是否会被重定向到以后,如果他们来自一个安全的页面,他们会重新定向到以后.

我也是使用NUnit 2.5和VS2008 Pro的方式.


这就是我想要测试的内容.我正处于我试图查看用户是否有效的部分(if语句).我不知道如何测试它.

public ActionResult Login(string returnUrl, FormCollection form, bool rememberMe)
       {
            LoginValidation loginValidation = new LoginValidation();
            try
            {
                UpdateModel(loginValidation, form.ToValueProvider());

            }
            catch
            {

                return View("Login");
            }

            if (ModelState.IsValid == true)
            {

                bool valid = authenticate.VerifyUser(loginValidation.UserName, loginValidation.Password);

                if (valid == false)
                {
                    ModelState.AddModelError("frm_Login", "Either the Password or UserName is invalid");

                }
                else if (string.IsNullOrEmpty(returnUrl) == false)
                {
                    /* if the user has been sent away from a page that requires them to login and they do 
                     * login then redirect them back to this area*/
                    return Redirect(returnUrl);
                }
                else
                {

                    FormsAuthentication.RedirectFromLoginPage(loginValidation.UserName, rememberMe);
                }

            }


            return View("Login");
        }
Run Code Online (Sandbox Code Playgroud)

kei*_*thm 7

您可以通过将自定义成员身份代码重构为两层来测试您的控制器和大部分自定义提供程序:仅与数据库交互的数据访问存储库,以及使用存储库组件提供Membership API的服务层.您可以在服务层验证参数,保存和强制执行EnablePasswordReset等参数,并将任何数据库异常或状态代码转换为适合控制器使用的形式.

当您使用自己的接口指定每个图层时,无论其实现方式如何,使用者都可以写入该接口.当您的应用程序运行时,您的提供程序当然是通过这些接口与数据库通信,但是为了测试,您可以模拟存储库或服务接口.您可以通过模拟存储库级别来测试服务层,而不必弄乱数据库或web.config文件,并且可以通过模拟服务层来测试控制器.如果您不想重构整个提供程序,如果只创建服务接口并让控制器使用它,您仍然可以测试控制器.

具体来说,如果有点冗长,您的存储库和服务接口可能类似于:

namespace Domain.Abstract {
    public interface IRepository {
        string ConnectionString { get; }
    }
}

namespace Domain.Abstract {
    public interface IUserRepository : IRepository {
        MembershipUser CreateUser(Guid userId, string userName, string password, PasswordFormat passwordFormat, string passwordSalt,
                string email, string passwordQuestion, string passwordAnswer, bool isApproved,
                DateTime currentTimeUtc, bool uniqueEmail);
        MembershipUser GetUser(Guid userId, bool updateLastActivity, DateTime currentTimeUtc);
        PasswordData GetPasswordData(Guid userId, bool updateLastLoginActivity, DateTime currentTimeUtc);
        void UpdatePasswordStatus(Guid userId, bool isAuthenticated, int maxInvalidPasswordAttempts, int passwordAttemptWindow, 
                      DateTime currentTimeUtc, bool updateLastLoginActivity, DateTime lastLoginDate, DateTime lastActivityDate);
        //....
    }
}

namespace Domain.Abstract {
  public interface IUserService {
    bool EnablePasswordRetrieval { get; }
    bool EnablePasswordReset { get; }
    bool RequiresQuestionAndAnswer { get; }
    bool RequiresUniqueEmail { get; }
    //....

    MembershipUser CreateUser(string applicationName, string userName, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved);
    MembershipUser GetUser(Guid userId, bool userIsOnline);
    bool ValidateUser(Guid userId, string password);
    //...
    }
}

namespace Domain.Concrete {
  public class UserService : IUserService {
    private IUserRepository _userRepository;


    public UserService(IUserRepository userRepository) {
        _userRepository = userRepository;
    }
    //...
    public bool ValidateUser(Guid userId, string password) {
        // validate applicationName and password here
        bool ret = false;
        try {
            PasswordData passwordData;
            ret = CheckPassword(userId, true, true, DateTime.UtcNow, out passwordData);
        }
        catch (ObjectLockedException e) {
            throw new RulesException("userName", Resource.User_AccountLockOut);
        }
        return ret;
    }

    private bool CheckPassword(Guid userId, string password, bool updateLastLoginActivityDate, bool failIfNotApproved,
                                DateTime currentTimeUtc, out PasswordData passwordData) {
        passwordData = _userRepository.GetPasswordData(userId, updateLastLoginActivityDate, currentTimeUtc);

        if (!passwordData.IsApproved && failIfNotApproved)
            return false;

        string encodedPassword = EncodePassword(password, passwordData.PasswordFormat, passwordData.PasswordSalt);
        bool isAuthenticated = passwordData.Password.Equals(encodedPassword);

        if (isAuthenticated && passwordData.FailedPasswordAttemptCount == 0 && passwordData.FailedPasswordAnswerAttemptCount == 0)
            return true;
        _userRepository.UpdatePasswordStatus(userId, isAuthenticated, _maxInvalidPasswordAttempts, _passwordAttemptWindow,
                                            currentTimeUtc, updateLastLoginActivityDate,
                                            isAuthenticated ? currentTimeUtc : passwordData.LastLoginDate,
                                            isAuthenticated ? currentTimeUtc : passwordData.LastActivityDate);

        return isAuthenticated;
    }
}
Run Code Online (Sandbox Code Playgroud)