模拟验证 DbSet 失败,GetEnumerator 未验证

Mocking verify DbSet failed with GetEnumerator unverified

我正在尝试使用最小起订量模拟我们的数据库。 在这里,我遇到的问题是 EntityFramework return DbSet 对象中的一些方法,我在代码中使用 foreach 对其进行了迭代。

现在我调用 VerifyNoOtherCalls();在此处定义的测试 methods.But 结束时,测试在我面前爆炸,因为 foreach 循环从 IEnumerable 接口调用 GetEnumerator(),我没有验证。但这是不可能的,因为 DbSet 本身没有实现 GetEnumerator() 并且 moq 不允许在 Lambda 中调用 ToList()。

现在我有两个问题:

  1. DbSet怎么可能实现了IEnumerable接口,却没有直接或在base中实现GetEnumerator方法class?
  2. 如何获得测试 运行?我已经在互联网上找到了一些说明,所以我决定自己模拟 DbSet:
        public static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
        {
            var queryable = sourceList.AsQueryable();

            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>())).Callback<T>((s) => sourceList.Add(s));

            return dbSet.Object;
        }

然而,这也不起作用。

关于您的第一个问题,DbSet<> has an explicit implementation for IQueryable.GetEnumerator()。这允许 DbSet 用作 IEnumerable<>s 而不会混淆智能感知,例如通常不会直接在 DbSet 上调用的方法。

我不确定为什么您发布的代码不起作用,但您可以尝试在 dbSet.AsIEnumerable<T>() 上模拟 GetEnumerator()

不过,在更高的层次上,我发现 mocking DbSet 的价值很小(将其视为 service您需要模拟和验证的方法)。我会专注于 伪造 它(将其视为一个集合,您可以指定其内容)。所以根据我的经验,调用 VerifyNoOtherCalls() 可能没有帮助。