如何在Entity Framework中模拟存储库和工作单元模式?

时间:2013-03-19 17:21:34

标签: c# .net unit-testing mocking nunit

我是Moq和单元测试的新手。我想用实体框架5测试我的存储库和工作单元模式。但我不明白我在哪里以及如何开始。

我的存储库界面:

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);
    }
}

我的工作单元界面:

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。现在我需要一个起点。

2 个答案:

答案 0 :(得分:3)

你真的不需要像编写它们那样测试你的存储库。原因在于,正如Mystere Man所提到的,你基本上只是包装了Entity Framework API。使用EF并使用我自己的存储库或某些DbContext时,我不担心在集成测试时间之前测试这些数据访问调用,原因已经说明了。

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

答案 1 :(得分:0)

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

有很多代码会通过Moq的上下文,但会在真实的环境中爆炸。因此,你不能依赖于具有EF上下文的假货,并且你必须使用集成测试。