【问题标题】:moq.As<>().Setup() does not seem to work after getting moq.Objectmoq.As<>().Setup() 在获取 moq.Object 后似乎不起作用
【发布时间】:2020-09-23 07:01:51
【问题描述】:

我从 Microsoft 关于使用 moq 测试 EF 的文章中得出一个小测试:Testing with a mocking framework

namespace TestingDemo
{
    public class BloggingContext : DbContext
    {
        public virtual DbSet<Blog> Blogs { get; set; }
    }

    public class Blog
    {
        public string Name { get; set; }
    }

    [TestClass]
    public class QueryTests
    {
        [TestMethod]
        public void Test()
        {
            var data = new List<Blog> { new Blog { Name = "AAA" } }.AsQueryable();
            var mockSet = new Mock<DbSet<Blog>>();
            //var a = mockSet.Object;
            mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
            mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
            mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
            mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
            var b = mockSet.Object.ToList();
        }
    }
}

在我取消注释 var a = mockSet.Object; 之前它工作正常 在此之后,我在var b = mockSet.Object.ToList();

System.NotImplementedException: '成员'IEnumerable.GetEnumerator' 尚未在从'DbSet`1' 继承的类型'DbSet`1Proxy' 上实现。 'DbSet`1' 的测试替身必须提供所使用的方法和属性的实现。'

我错过了什么吗?

更新: 使用起订量 4.10.1、EF 6.2.0、VS 社区 2019 16.6.1、.NET 4.7.2

【问题讨论】:

  • 我建议您坚持链接文档中显示的内容。无论如何都不需要在设置的早期访问模拟对象
  • 嗯...这很可能是因为模拟创建对象使用延迟初始化,当您调用对象时,一旦创建它就想再次创建它。初始化负责 DynamicProxy 创建,因此您添加的任何其他接口都不会被“模拟”...

标签: c# entity-framework linq moq


【解决方案1】:

您实际上还需要创建 DbContext 模拟,例如:

var context = new Mock<BloggingDbContext>();

var mockSet = new Mock<DbSet<Blog>>();

 mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
 mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
 mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
 mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

context.Setup(c => c.Blogs).Returns(mockSet.Object);

var blogs = context.Object.Blogs.ToList(); // usage 

【讨论】:

  • 你能重现原来的错误吗?如果您在进行所提供示例中的设置之前引入 var a = mockSet.Object; 会发生什么
  • @Nkosi 不,这是我们过去在 .net 核心应用程序中所做的,它工作正常
  • 我的想法完全正确。我想知道问题是否可重现,因为它应该从 OP 中当前显示的内容开始工作
  • 当然,但我需要了解为什么 var a = mockSet.Object; 在调用 moq.As().Setup() 之前会改变行为。调用 moq.Setup() 工作正常。
  • 您不需要创建数据库上下文实例/模拟来模拟数据库集。
【解决方案2】:

问题是在获得模拟对象的实例 (mockSet.Object) 之后添加 IQueryable&lt;T&gt; 设置;它不起作用,这也是为什么一旦您将分配注释到a 后它就可以正常工作的原因。只有在为要使用的行为添加设置后,才能检索模拟对象。

有趣的是,一旦您添加了这些设置,您就可以随时更改它们(使用其他设置覆盖)。您只需在检索模拟对象之前进行初始注册。我一直用我的系统模拟库来做这件事。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-28
    • 2020-07-30
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 2016-02-01
    • 2020-09-23
    • 2010-12-05
    相关资源
    最近更新 更多