【问题标题】:Moq Setup Adding With Same "Filter" instead of overwritingMoq 设置使用相同的“过滤器”添加而不是覆盖
【发布时间】:2021-04-08 21:33:12
【问题描述】:

我正在尝试在 Moq 中模拟一个 DbSet,我可以在其中添加到 DbSet 中的实体列表中。换句话说,一个可变的 DbSet.

我为此编写了一些扩展方法,但已将问题简化为一个测试。

在 Moq 中如果您使用相同的参数(过滤器)设置相同的调用,则替换设置?

但是,下面这个单元测试显示它被添加了?

请参阅“下面抛出“预期的集合包含 1 个项目,但找到了 2 个。”

        [Fact]
        public void Add2Test()
        {
            var contextMock = new Mock<IDbContext>();
            List<MyEntity> data = new List<MyEntity>(){new MyEntity()};
            var queryable = data.AsQueryable();
            var mockDbSet = new Mock<DbSet<MyEntity>>();
            mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(queryable.Provider);
            mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(queryable.Expression);
            mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
            mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
            contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(0);
            contextMock.Setup(x => x.Set<MyEntity>()).Returns(mockDbSet.Object);
            contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
            // let's do it again
            data = new List<MyEntity>() { new MyEntity() };
            queryable = data.AsQueryable();
            mockDbSet = new Mock<DbSet<MyEntity>>();
            mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(queryable.Provider);
            mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(queryable.Expression);
            mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
            mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
            contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
            contextMock.Setup(x => x.Set<MyEntity>()).Returns(mockDbSet.Object);
            // below throws "Expected collection to contain 1 item(s), but found 2."
            contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
        }

【问题讨论】:

  • 如果你评论let's do it again 的所有行,除了最后一行,即contextMock.Setup(x =&gt; x.Set&lt;MyEntity&gt;()).Returns(mockDbSet.Object);,你会得到同样的错误吗?如果您使用It.IsAny&lt;MyEntity&gt; 进行设置,您会看到同样的错误吗?
  • >>如果你注释所有行让我们再做一次,除了最后一行即 contextMock.Setup(x => x.Set()).Returns(mockDbSet.Object); >如果您使用 It.IsAny
  • 如果这里的意图是刷新数据那么你需要初始化对象mockDbSet = new Mock&lt;DbSet&lt;MyEntity&gt;&gt;();吗?我相信,如果您评论该行并保持其余内容不变,那么您将不会得到您在问题中提到的行为......现在关于您的行为,我相信您会明白这一点,因为对象引用在@987654326 行发生了变化@ 这就是为什么它返回 2 个设置计数..
  • 所以,你的假设是因为有第二个返回对象,这就是为什么有两个设置?
  • 是的,这是我的假设。

标签: c# testing moq


【解决方案1】:

根据我在编写 EntityFrameworkCore.TestingMemoryCache.Testing 等库时的观察,Moq 不会替换/覆盖相同的现有设置。

虽然这是一个最小起订量的实现细节,但目前如果您多次设置相同的表达式,则将使用最后添加的设置。

void Main()
{
    var mock = new Mock<IFoo>();
    mock.Setup(x => x.Bar()).Returns("A");
    mock.Setup(x => x.Bar()).Returns("B");
    var mocked = mock.Object;
    Console.WriteLine(mocked.Bar());
    Console.WriteLine(mock.Setups.Select(x => x.ToString()));
}

public interface IFoo
{
    public string Bar();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-17
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 2013-05-04
    • 2013-06-02
    相关资源
    最近更新 更多