[英]Creating repositories for Unit Testing
我已經用C#,MVC,實體框架,LINQ等編寫了一個Web應用程序,現在我想為整個項目追溯創建單元測試。
我知道,為了編寫有效的單元測試,我需要為模型創建存儲庫,以便可以對它們進行模擬,因此實體框架將對數據庫產生任何影響。
我有3個主要模型; 類別,密碼,UserPassword。
類別包含類別和密碼。 密碼包含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查詢...看起來如何?
如果您要編寫單元測試,則所有LINQ to Entities都應位於接口后面,
例如
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))
.....
}
EDIT2:剛注意到.SingleOrDefault()
,而不是返回List<Category>
,而不是返回Category
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.