如何在实体框架中模拟存储库和工作单元模式

本文关键字:工作 单元 模式 存储 模拟 实体 框架 | 更新日期: 2023-09-27 18:04:38

我是Moq和单元测试的新手。我想测试我的存储库和工作单元模式与实体框架5。但是我不知道从哪里开始,怎样开始。

My Repository Interface:

public interface ISmRepository<T>
{
    void Add(T entity);
    void Remove(T entity);
    void Update(T entity);
    IQueryable<T> SearchFor(Expression<Func<T, bool>> expression);
    IQueryable<T> GetAll();
    T GetById(Int64 id);
} 

我的库:

public class SmReporitory<T> : ISmRepository<T> where T : class, IEntity, new()
{
    private readonly DbSet<T> _dbSet;
    private readonly DbContext _dbContext;
    public SmReporitory(DbContext dbContext)
    {
        _dbSet = dbContext.Set<T>();
        _dbContext = dbContext;
    }
    public void Add(T entity)
    {
        _dbSet.Add(entity);
    }
    public void Remove(T entity)
    {
        _dbSet.Remove(entity);
    }
    public void Update(T entity)
    {
        _dbContext.Entry(entity).State = EntityState.Modified;
    }
    public IQueryable<T> SearchFor(Expression<Func<T, bool>> expression)
    {
        return _dbSet.Where(expression);
    }
    public IQueryable<T> GetAll()
    {
        return _dbSet;
    }
    public T GetById(long id)
    {
        return _dbSet.FirstOrDefault(x => x.Id == id);
    }
}

My Unit Of Work接口:

public interface ISmUnitOfWork : IDisposable
{
    ISmRepository<BreakdownCause> BreakdownCasus { get; }
    ISmRepository<BreakDownType> BreakDownTypes { get; }
    ISmRepository<CompanyInformation> CompanyInformations { get; }
    void Save();
}

我的工作单位实施:

public class SmUnitOfWork : ISmUnitOfWork
{
    private readonly DbContext _dbContext;
    private ISmRepository<BreakDownType> _breakDownTypes;
    private ISmRepository<BreakdownCause> _breakdownCasus;
    private ISmRepository<CompanyInformation> _companyInformations;
    public SmUnitOfWork() : this(new SmDbContext())
    {
    }
    public SmUnitOfWork(SmDbContext smDbContext)
    {
        _dbContext = smDbContext;
    }
    public ISmRepository<BreakdownCause> BreakdownCasus
    {
        get { return _breakdownCasus ?? (_breakdownCasus = new SmReporitory<BreakdownCause>(_dbContext)); }
    }
    public ISmRepository<BreakDownType> BreakDownTypes
    {
        get { return _breakDownTypes ?? (_breakDownTypes = new SmReporitory<BreakDownType>(_dbContext)); }
    }
    public ISmRepository<CompanyInformation> CompanyInformations
    {
        get { return _companyInformations ?? (_companyInformations = new SmReporitory<CompanyInformation>(_dbContext)); }
    }
    public void Save()
    {
        try
        {
            _dbContext.SaveChanges();
        }
        catch
        {
            throw;
        }
    }
    public void Dispose()
    {
        if (_dbContext!=null)
        {
            _dbContext.Dispose();
        }
    }

现在我想测试ISmRepository接口方法。

我已经在类库项目中引用了NUnit和Moq。现在我需要一个起始点

如何在实体框架中模拟存储库和工作单元模式

您真的不需要在编写存储库时对其进行测试。原因是,正如mysterman所暗示的,你基本上只是包装实体框架API。当使用EF并使用我自己的存储库或一些DbContext时,我不担心在集成测试时间之前测试这些数据访问调用,原因已经说明了。

但是,您可以(也应该)模拟您的存储库和工作单元来测试所有依赖于它们的其他代码。通过测试你的存储库,你实际上是在测试实体框架的功能,我相信它已经被测试得比你想象的更彻底了。您可以做的一件事是不要将业务逻辑放入直接与EF交互的存储库中,而是将其移到利用存储库进行数据访问的另一层。

简短的回答是,你真的不能。至少不完全是这样。这样做的原因是,由于固有的sql转换,模拟的EF上下文的行为与真实的上下文不同。

有很多代码会传递一个Moq的上下文,但在一个真正的上下文中会爆炸。因此,您不能依赖于EF上下文的Moqing of fakes,您必须使用集成测试。