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

How can I mock the Set <entity> method of DbContext?

我想为那个通用存储库模式做单元测试,我已经用各种方法尝试过了,但我做不到,最接近的做法是在这里我留下我已经完成的实现

    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>
{

}

但是我收到这个错误

希望你能帮帮我,我已经来了两个小时了

The member 'IEnumerable.GetEnumerator' has not been implemented on type 'DbSet1Proxy' which inherits from 'DbSet1'. Test doubles for 'DbSet`1' must provide implementations of methods and properties that are used.

这个错误不同于这个post

我刚刚尝试了那个解决方案,但我仍然处于相同状态

实际上我所做的是以下说明

  1. 我上传了 4.8 的最小起订量版本

  2. 我改这个

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

为此

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

它奏效了,可以按照 post 45558663 # 45558663

中的说明进行一般性操作

但我所做的本质就是那样。