jeudi 25 août 2016

How to unit test an MVC project that uses entity framework 6, linq, and that is very database dependent?

I know this is a very broad question and that is actually my main problem. I'm new to unit testing and I don't know where to find useful resources because I'm not even sure what exactly to search for. I've been assigned to add unit testing to an MVC website project and this is the first time my team has tried to implement either, but the old methods we've been using are outdated and not optimized so we are trying to embrace newer and more efficient methods.

The new MVC project is still small and is a rewrite of an old legacy website that is monstrous and unmanageable with manual testing that takes hours to complete after every little change. We want to build something better and believe MVC, Entity Framework, and unit testing is the way to do that. Here is how I've set our project up according to other MVC projects we've researched.

Here is a basic controller ActionResult...

public ActionResult SignUp()
{
    return View("SignUp");
}

[HttpPost]
public ActionResult SignUp(UserSignUpView userSignUpView)
{
    if (User.Identity.IsAuthenticated)
    {
        return RedirectToAction("Index", "Home");
    }
    else if (!ModelState.IsValid)
    {
        return View(userSignUpView);
    }

    string error = userManagerModel.CheckIfAccountExists(userSignUpView.LoginName, userSignUpView.Email);

    if (error != null)
    {
        ModelState.AddModelError("", error);
        return View("SignUp");
    }
    else
    {
        userManagerModel.AddAccount(userSignUpView);
        FormsAuthentication.SetAuthCookie(userSignUpView.LoginName, false);
        return RedirectToAction("Welcome", "Home");
    }
}

Here is a basic Model...

public class UserSignUpView
{
    [Key]
    public int UserID { get; set; }

    [Display(Name = "Login ID")]
    [Required(ErrorMessage = "* Required")]
    public string LoginName { get; set; }

    [Display(Name = "Email")]
    [Required(ErrorMessage = "* Required")]
    [EmailAddress(ErrorMessage = "Invalid Email Address")]
    public string Email { get; set; }

    [Display(Name = "Password")]
    [Required(ErrorMessage = "* Required")]
    [RegularExpression(@"^(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-zA-Z]).{8,20}$",
        ErrorMessage = "Password must be between 8 and 20 characters long. Password must also contain at least 1 upper case letter, 1 number, and 1 special character.")]
    public string Password { get; set; }

    [Display(Name = "Confirm Password")]
    [Required(ErrorMessage = "* Required")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

Here are the associated helper methods for the SignUp() action...

    public string CheckIfAccountExists(string loginName, string email)
    {
        using (var db = new Database())
        {
            if (db.Users.Where(o => o.LoginName.Equals(loginName)).Any()
                && db.Users.Where(o => o.Email.Equals(email)).Any())
            {
                return "Both Login and Email already exists";
            }
            else if (db.Users.Where(o => o.LoginName.Equals(loginName)).Any())
            {
                return "Login Name already taken.";
            }
            else if (db.Users.Where(o => o.Email.Equals(email)).Any())
            {
                return "An account with this email already exists.";
            }
        }
        return null;
    }

    public void AddAccount(UserSignUpView userSignUpView)
    {
        using (var db = new Database())
        {
            string securePassword = //method that adds salt and hashes userSignUpView.Password
            User user = new User();
            user.LoginName = userSignUpView.LoginName;
            user.SecurePassword = securePassword;
            user.Email = userSignUpView.Email;

            db.Users.Add(user);
            db.SaveChanges();
        }
    }

So I'm trying to add unit testing and from what I've read mocking the database is my best bet but all my attempts have failed. There are resources everywhere for linq, entity framework, mocking data, mvc, and unit testing but I haven't had any luck finding something for all of them working together written after 2008. Is there a better way to set these pieces up that is more cohesive to unit testing? I probably sound like child grasping at straws with a lot of this but we just want to get out from under the terrible legacy practices that we've been stuck with for so long.

TLDR; Are there any decent and up-to-date tutorials on unit testing for MVC entity framework?

Aucun commentaire:

Enregistrer un commentaire