如何模拟DbContext的Set <entity>方法?

时间:2017-12-28 20:00:44

标签: c# entity-framework unit-testing moq repository-pattern

我想对该通用存储库模式进行单元测试,我已经尝试过各种各样的方式,我无法得到它,最接近的事情就是这里我离开了我已经完成的实现

    public abstract class Repository<TEntity, TKey> : IRepository<TEntity, TKey> where TEntity : Entity<TKey>
{
    private readonly ValcalContext _context;

    private readonly IUnitOfWork _unitOfWork;

    public IUnitOfWork UnitOfWork => _unitOfWork;

    public Repository(IUnitOfWork uow)
    {
        _context = uow.Context as ValcalContext;
        _unitOfWork = uow;
    }

    public List<TEntity> All => _context.Set<TEntity>().ToList();

    public List<TEntity> AllEager(params Expression<Func<TEntity, object>>[] includes)
    {
        IQueryable<TEntity> query = _context.Set<TEntity>();
        foreach (var include in includes)
        {
            query = query.Include(include);
        }
        return query.ToList();
    }

    public TEntity Find(TKey id)
    {
        return _context.Set<TEntity>().Find(id);
    }

    public IEnumerable<TEntity> GetAll()
    {
        return _context.Set<TEntity>().ToList();
    }

    public void Insert(TEntity item)
    {
        _context.Entry(item).State = EntityState.Added;
    }

    public void Delete(TEntity entity)
    {
        var item = _context.Set<TEntity>().Find(entity.Id);
        _context.Set<TEntity>().Remove(item);
    }

    public void Delete(TKey id)
    {
        var item = _context.Set<TEntity>().Find(id);
        _context.Set<TEntity>().Remove(item);
    }

    public void Update(TEntity item)
    {
        _context.Set<TEntity>().Attach(item);
        _context.Entry(item).State = EntityState.Modified;
    }

    public void Dispose()
    {
        if (_context != null)
            _context.Dispose();
    }
}

这是我的dbContext

 public class ValcalContext : DbContext,IValcalContext
{
    public ValcalContext() : base("ValcalConnection")
    {
    }

    public static ValcalContext Create()
    {
        return new ValcalContext();

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        AddConventions(modelBuilder);

        var typesToRegister = TypesToRegister();

        AddConfigurationsMapping(modelBuilder, typesToRegister);

        base.OnModelCreating(modelBuilder);
    }

    #region Private Methods

    /// <summary>
    /// /Agrega las convenciones de mapeo a la base de dato
    /// </summary>
    /// <param name="modelBuilder"></param>
    private void AddConventions(DbModelBuilder modelBuilder)
    {
        modelBuilder.Types().Configure(entity => entity.ToTable(entity.ClrType.Name.ToLowerUnderscored()));
        modelBuilder.Conventions.Add(new UnderScoredLowerCaseConvention());
    }


    private static IEnumerable<Type> TypesToRegister()
    {
        var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
            .Where(type => !string.IsNullOrEmpty(type.Namespace))
            .Where(type => type.BaseType != null && type.BaseType.IsGenericType
                           && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
        return typesToRegister;
    }


    private static void AddConfigurationsMapping(DbModelBuilder modelBuilder, IEnumerable<Type> typesToRegister)
    {
        foreach (var configurationInstance in typesToRegister.Select(Activator.CreateInstance))
        {
            modelBuilder.Configurations.Add((dynamic)configurationInstance);
        }
    }
    #endregion
}

我想为该通用存储库模式进行单元测试,现在我有了这个

    [TestClass]
public class RepositoryUnitTest
{


    [TestMethod]
    public void Sample()
    {
        //arrange
        var mockEntityTest = new Mock<DbSet<EntityTest>>();

        var unitOfWork = new  Mock<IUnitOfWork>();
        var valcalContext = new Mock<ValcalContext>();

        valcalContext.Setup(vc => vc.Set<EntityTest>()).Returns(mockEntityTest.Object);
        var mock = valcalContext.Object;

        unitOfWork.Setup(uow => uow.Context).Returns(mock);

        var repository = new RepositoryTest(unitOfWork.Object);

        //act
        var entityTests = repository.All;
        //assert
        Assert.AreEqual(entityTests.ToList().Count,0);
    }

}

 public class RepositoryTest : Repository<EntityTest, int>
{
    public RepositoryTest(IUnitOfWork uow) : base(uow)
    {
    }
}
 public  class EntityTest : Entity<int>
{

}

但我收到此错误

error

details error

我希望你能帮助我,我已经在这里待了两个小时

  

会员&#39; IEnumerable.GetEnumerator&#39;一直没有   在类型&#39; DbSet 1Proxy' which inherits from 'DbSet 1&#39;上实施。测试   为DbSet`1&#39;加倍必须提供方法和实现   使用的属性。

此错误与此帖Moq DbSet NotImplementedException

不同

我刚试过这个解决方案而且我还在同一个

1 个答案:

答案 0 :(得分:1)

我真正做的是以下内容,以便明确

  1. 我上传了4.8

  2. 的moq版本
  3. 我改变了这个

    [TestMethod]
    public void Sample()
    {
        //arrange
        var mockEntityTest = new Mock<DbSet<EntityTest>>();
    
        var unitOfWork = new  Mock<IUnitOfWork>();
        var valcalContext = new Mock<ValcalContext>();
    
        valcalContext.Setup(vc => vc.Set<EntityTest>()).Returns(mockEntityTest.Object);
        var mock = valcalContext.Object;
    
        unitOfWork.Setup(uow => uow.Context).Returns(mock);
    
        var repository = new RepositoryTest(unitOfWork.Object);
    
        //act
        var entityTests = repository.All;
        //assert
        Assert.AreEqual(entityTests.ToList().Count,0);
    }
    
  4. 这个

    [TestMethod]
    public void Sample()
    {
        //arrange
        var mockEntityTest = new Mock<DbSet<EntityTest>>();
        var list = new List<EntityTest>();
        var queryable = list.AsQueryable();
        mockEntityTest.As<IQueryable<EntityTest>>().Setup(m => m.Provider).Returns(queryable.Provider);
        mockEntityTest.As<IQueryable<EntityTest>>().Setup(m => m.Expression).Returns(queryable.Expression);
        mockEntityTest.As<IQueryable<EntityTest>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
        mockEntityTest.As<IQueryable<EntityTest>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
    
        var unitOfWork = new  Mock<IUnitOfWork>();
        var valcalContext = new Mock<ValcalContext>();
    
        valcalContext.Setup(vc => vc.Set<EntityTest>()).Returns(mockEntityTest.Object);
        var mock = valcalContext.Object;
    
        unitOfWork.Setup(uow => uow.Context).Returns(mock);
    
        var repository = new RepositoryTest(unitOfWork.Object);
    
        //act
        var entityTests = repository.All;
        //assert
        Assert.AreEqual(entityTests.ToList().Count,0);
    }
    

    并且它有效,这可以通过本文中所解释的一般性地完成How do I go about unit testing with Entity Framework and Moq? 45558663#45558663

    但我所做的就是那个。