【问题标题】:How can I mock the Set <entity> method of DbContext? [duplicate]如何模拟 DbContext 的 Set <entity> 方法? [复制]
【发布时间】:2018-06-09 08:47:44
【问题描述】:

我想为通用存储库模式进行单元测试,我已经以各种方式尝试过,但我无法得到它,最接近的事情就是在这里我留下我已经完成的实现

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

}

但我收到此错误

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

成员 'IEnumerable.GetEnumerator' 尚未被 在“DbSet1Proxy' which inherits from 'DbSet1”类型上实现。测试 'DbSet`1' 的双打必须提供方法的实现和 使用的属性。

这个错误和这个帖子不一样Moq DbSet NotImplementedException

我刚刚尝试了那个解决方案,但我还是一样

【问题讨论】:

  • 我刚刚尝试了他们在那篇帖子中所说的内容,但它不起作用我一直给出同样的错误。你知道怎么可能吗?
  • 看看我这里给的答案stackoverflow.com/a/45558663/5233410
  • 您在一个空的模拟 DbSet 上调用 ToList 扩展。这就是您收到错误的原因。
  • 是的,对我有用,谢谢,谢谢

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


【解决方案1】:

我确实做了以下说明

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

它奏效了,这可以按照这篇文章How do I go about unit testing with Entity Framework and Moq? 45558663 # 45558663 中的说明进行一般性操作

但我所做的事情的本质就是这样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-30
    • 1970-01-01
    • 2014-12-13
    • 2020-08-23
    • 2019-09-26
    • 1970-01-01
    • 2019-06-29
    相关资源
    最近更新 更多