2014-12-01 117 views
0

我已經用C#,MVC,實體框架,LINQ等編寫了一個Web應用程序......現在我想追溯地爲整個項目創建單元測試。爲單元測試創​​建存儲庫

據我所知,爲了編寫有效的單元測試,我需要爲模型創建存儲庫,以便它們可以被模擬,因此實體框架將對數據庫執行任何命中。

我有3個主要模型;類別,密碼,用戶密碼。

類別包含類別和密碼。密碼包含UserPasswords(鏈接到用戶帳戶)。所以我創建了3個存儲庫,其基本方法如:創建,刪除,更新等..

然而,看着這個LINQ查詢:

var selectedCategoryItem = DatabaseContext.Categories 
       .Where(c => c.CategoryId == ParentCategoryId) 
       .Include(c => c.SubCategories) 
       .Include(c => c.Passwords) 
       .Include(c => c.Passwords.Select(p => p.Creator)) 
       .ToList() 
       .Select(c => new Category() 
       { 

       SubCategories = c.SubCategories 
          .Where(sub => !sub.Deleted) 
          .OrderBy(sub => sub.CategoryOrder) 
          .ToList(),       //make sure only undeleted subcategories are returned 

       Passwords = c.Passwords 
          .Where(pass => !pass.Deleted 
          && (
          (UserPasswordList.Any(up => up.PasswordId == pass.PasswordId && up.Id == UserId)) 
          || (userIsAdmin && ApplicationSettings.Default.AdminsHaveAccessToAllPasswords) 
          || pass.Creator_Id == UserId 
          ) 
          ) //make sure only undeleted passwords - that the current user has acccess to - are returned 
          .OrderBy(pass => pass.PasswordOrder) 
          .ToList(), 

       CategoryId = c.CategoryId, 
       CategoryName = c.CategoryName, 
       Category_ParentID = c.Category_ParentID, 
       CategoryOrder = c.CategoryOrder, 
       Parent_Category = c.Parent_Category, 
       Deleted = c.Deleted 
       }) 
       .SingleOrDefault(); 

如果倉庫只是像保存,更新,刪除,插入,FindById等基本方法....我應該如何將查詢分解成存儲庫?這裏還有很多商業邏輯,例如過濾用戶可以訪問的密碼,應該在哪裏?

我讀了一些關於返回IQueryable對象的信息,以便可以在服務層中更改LINQ查詢......看起來如何?

+1

你看着努力呢? HTTPS://effort.codeplex。com/ – Bringer128 2014-12-02 01:19:16

回答

2

如果你想要編寫單元測試,所有的LINQ到實體的,應該是一個接口之後,

例如

public interface ICategoryRepository { 
    List<Category> GetCategoriesForParentId(int id); 
} 

然後是一個實現該方法幷包含LINQ和過濾邏輯的類。

現在在需要訪問它的客戶端類中,通過構造函數傳入ICategoryRepository(推薦)。對於單元測試,將一個模擬庫傳入構造函數,該構造函數返回一個預定義的結果集。

爲了測試實際的存儲庫過濾/轉換邏輯,我發現最好的方法是使用SQLite或SQL CE,並進行集成測試,該測試加載預定義的數據庫,該數據庫處於已知狀態從保存的副本,或重新創建它每次測試),並有一個集成測試,在SQLite的或SQL CE數據庫指向存儲庫類,而不是你真正的使之始終處於已知狀態,運行查詢,檢查結果集。

編輯:

無論是通過由庫需要進入方法的細節,如:

List<Category> GetCategoriesForParentIdAnduser(int id, int passwordId, int userId); 

或者,如用戶可能是整個網站,你可以通過一個

public interface IUserConfig { 
    int PasswordId{ get; set; } 
    int UserId { get; set;} 
} 


// Constructor for CategoryRepository : ICategoryRepository 
public CategoryRepository(DbContext context, IUserConfig) 
{ 
    .... 
} 

然後

public List<Category> GetCategoriesForParentId(int id){ 
    return _context.Categories 
       ..... 
       Passwords = c.Passwords.Where(
          ..... 
          (UserPasswordList.Any(up => up.PasswordId == _userConfig.PasswordId 
                && up.Id == _userConfig.UserId))        
       ..... 
} 

編輯2:剛注意到.SingleOrDefault(),而不是返回List<Category>你會返回Category

+0

我不能理解的是,讓我們拿列表 GetCategoriesForParentId - 這將返回一個類別列表,但我需要返回一個類別和密碼列表...所以這將如何使用存儲庫模式實現? – binks 2014-12-01 23:41:26

+0

2個倉庫,2個電話 – 2014-12-01 23:42:52

+0

因此,類似於: var root = new Category(){subcategories = GetCategoriesForParentId(1),password = GetPasswordsForParentId(1)}; – binks 2014-12-01 23:43:58