2016-08-25 5 views
1

私はこれが非常に広い質問であり、それが実際に私の主な問題であることを知っています。私は単体テストに慣れていないので、正確に何を検索するか分からないので、役に立つリソースを見つける場所がわかりません。私はユニットテストをMVC Webサイトプロジェクトに追加するように割り当てられました。これは私のチームが実装しようとしたのは初めてのことですが、古いメソッドは古く、最適化されていないので、より効率的な方法。Entity-Framework 6、Linqを使用し、かなりデータベースに依存するMVCプロジェクトの単体テスト方法

新しいMVCプロジェクトは依然として小さく、些細なことで手作業によるテストでは扱いにくい古いWebサイトを書き直したもので、少しずつ変更してから完了するまでに数時間かかります。 MVC、Entity Framework、単体テストがそれを実現する方法だと考えています。ここで私が研究している他のMVCプロジェクトに従ってプロジェクトを設定したのです。ここ

は、基本的なコントローラの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"); 
    } 
} 

は、基本モデルである...ここ

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(@"^(?=.*[[email protected]#$&*])(?=.*[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; } 
} 

はサインアップ()アクションのための関連するヘルパーメソッドであります...

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(); 
     } 
    } 

だから私はユニットテストを追加しようと、私は、データベースをからかっ読んだからだが、私の最善の策であるが、私の試みはすべて失敗しました。 linq、エンティティフレームワーク、mockingデータ、mvc、ユニットテストのためのリソースはどこにでもありますが、2008年以降に一緒に作業している人にとっては何も見つかりませんでした。これらの部分を設定する方法はありますか?単体テストに一貫性がありますか?私はたぶん子供がこのようなストローで握っているように聞こえるかもしれませんが、私たちが長年にわたって抱えてきた恐ろしい伝統的な慣行の下から脱出したいだけです。

TLDR; MVCエンティティフレームワークの単体テストに関する上級チュートリアルがありますか?

+0

例えば

は、あなたはそれがより多くのテスト可能にするためにあなたのコードをリファクタリングについての提案を開いていますか? – Nkosi

+0

最も確実です。私は非常に多くのデータベース呼び出しとデータベース全体の依存関係でリファクタリングする必要があると考えました。単体テストは、このアプローチではうまく機能していないように思われます。私は慣れているだけでなく、最良の方法を見つけたいと思っています。 – LittleBachman

+0

可能な回答が多すぎるか、この回答の回答が長すぎます。回答セットを絞り込むか、いくつかの段落で回答できる問題を特定するための詳細を追加してください。 – Nkosi

答えて

1

単純なコントローラの例では、どのようにしてそのコントローラをテストしやすくするのですか?

初心者として、実装の依存関係を抽象化することを検討する必要があります。

したがって、userManagerModelFormsAuthenticationを抽象化することを意味します。あなたは、コントローラのアクションをテストしたいときに偽/嘲笑の実装に置き換えることができるように

public interface IUserManager { 
    string CheckIfAccountExists(string loginName, string email); 
    void AddAccount(UserSignUpView userSignUpView); 
} 

public interface IAuthenticationService { 
    void SetAuthCookie(string userName, bool createPersistentCookie); 
} 

(離れて静的クラスとのカップリングから滞在してみてください)。

public class AccountController : Controller { 
    IUserManager userManagerModel; 
    IAuthenticationService formsAuthentication; 

    public AccountController(IUserManager userManagerModel, IAuthenticationService formsAuthentication) { 
     this.userManagerModel = userManagerModel; 
     this.formsAuthentication = formsAuthentication; 
    } 

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

    [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(userSignUpView); 
     } else { 
      userManagerModel.AddAccount(userSignUpView); 
      formsAuthentication.SetAuthCookie(userSignUpView.LoginName, false); 
      return RedirectToAction("Welcome", "Home"); 
     } 
    } 
} 

はほとんどあなたがもともと持っていたもののように見えますが、あなたはuserManagerModelインターフェイスではなく具体的​​なクラスであることがわかります。

コントローラをデータベースに緊密に接続することなくコントローラの機能をテストするために、手動または擬似フレームワークで偽物/モックを作成できます。

プロダクションクラスがインターフェイスを実装し、本番環境で期待される機能を提供するようにします。

public class FormsAuthenticationService : IAuthenticationService { 
    public void SetAuthCookie(string userName, bool createPersistentCookie) { 
     FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); 
    } 
} 
+0

これは私が読んだこと以外の何もかもよりも既に役立っています。ありがとうございます。私は依存関係が理想的ではないことを知っています。私はそれらにアプローチする最善の方法を確信していませんでした。 – LittleBachman

+1

この記事を見てくださいhttp://www.danylkoweb.com/Blog/the-ultimate-guide-to-unit-testing-in-aspnet-mvc-E2 – Nkosi

+0

@ Nkosiこれは完璧です、それはブログのようですこのような本当に良い情報を持った記事は、何かの情報を見つけようとするときに起きることは決してありません。また、Interfaces対Static Classesでは、少なくとも、より具体的なものを研究しています。ありがとうございました。 – LittleBachman

関連する問題