为单元测试创建存储库

本文关键字:存储 创建 单元测试 | 更新日期: 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