为单元测试创建存储库
本文关键字:存储 创建 单元测试 | 更新日期: 2023-09-27 18:32:47
我已经用C#,MVC,Entity-Frame,LINQ等编写了一个Web应用程序......现在我想为整个项目追溯创建单元测试。
我知道为了编写有效的单元测试,我需要为模型创建存储库,以便可以模拟它们,因此实体框架将对数据库进行任何点击。
我有 3 个主要模型;类别、密码、用户密码。
类别包含类别和密码。密码包含用户密码(链接到用户帐户(。所以我用基本方法创建了 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))
.....
}
编辑2:刚刚注意到.SingleOrDefault()
,而不是返回List<Category>
你会返回Category
。