模拟DBSet时的问题

时间:2018-06-21 12:42:16

标签: c# entity-framework-6 moq iqueryable dbset

要对应用程序进行单元测试,我们使用Moq创建了DbSet的模拟,如下所示:

public static class RepositoryHelper
{
    public static Mock<DbSet<T>> GetQueryableMockDbSet<T>(ICollection<T> sourceList, bool queryDeletedEntities = false) where T : EntityBase
    {
        IQueryable<T> queryable = queryDeletedEntities
            ? sourceList.AsQueryable()
            : sourceList.AsQueryable().Where(e => !e.IsDeleted);

        var dbSet = new Mock<DbSet<T>>();
        dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
        dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
        dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
        dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());

        dbSet.Setup(d => d.Add(It.IsAny<T>())).Returns<T>(e =>
        {
            sourceList.Add(e);
            return e;
        });

        dbSet.Setup(d => d.Remove(It.IsAny<T>())).Returns<T>(e =>
        {
            sourceList.Remove(e);
            return e;
        });

        return dbSet;
    }
}

我们存储库的相关部分是这样的:

public class Repository<T> : IRepository<T>
    where T : EntityBase
{
    public Repository(DbSet<T> set)
    {
        Set = set;
    }

    /// <summary>
    /// Returns the orginal entity framework set.
    /// Use this property to access change tracked or all existing entities.
    /// </summary>
    protected DbSet<T> Set { get; }

    /// <summary>
    /// Returns the query.
    /// Use this property as a foundation for all get queries.
    /// </summary>
    protected virtual IQueryable<T> Query => Set;

    public IQueryable<T> Get()
    {
        return Query;
    }

    protected static IQueryable<TDerived> ApplyIncludes<TDerived>(IQueryable<TDerived> query, Expression<Func<TDerived, object>>[] propertiesToInclude) where TDerived : T
    {
        if (propertiesToInclude.Length != 0)
        {
            foreach (var propertyToInclude in propertiesToInclude)
            {
                query = query.Include(propertyToInclude);
            }
        }

        return query;
    }
}

我的问题是,在影响query时,模拟DbSet Repository.ApplyIncludesquery = query.Include(propertyToInclude);中为空(正在使用System.Data.Entity.QueryableExtensions中的include);真正的实施效果很好。另外,如果我将Repository.Query修改为返回protected virtual IQueryable<T> Query => Set.Where(e => true);,则会解决此问题。
queryRepository.ApplyIncludes的类型在仅使用Castle.Proxies.DbSet'1Proxy时为Set,在使用System.Linq.EnumerableQuery<EntityType>时为Set.Where(e => true)

我不确定我们是否错过了RepositoryHelper.GetQueryableMockDbSet中的某些内容,是否偶然发现了Moq或其他错误。我还没有找到解决RepositoryHelper.GetQueryableMockDbSet中问题的方法,也不想在生产性代码中包含protected virtual IQueryable<T> Query => Set.Where(e => true);(因为它只能解决测试问题)。如果有人能指出我正确的方向,我将不胜感激。

0 个答案:

没有答案