【问题标题】:Using Moq with Linq Any()将起订量与 Linq Any() 一起使用
【发布时间】:2013-11-26 13:50:26
【问题描述】:

我有一个类似于下面的设置:

    [TestMethod]
    public void NoIntegers()
    {
        Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
        Mock<IEnumerable<int>> mockIntegers = new Mock<IEnumerable<int>>(MockBehavior.Strict);

        mockBar
            .SetupGet(x => x.Integers)
            .Returns(mockIntegers.Object);

        mockIntegers
            .Setup(x => x.Any())
            .Returns(false);

        Assert.IsFalse(new Foo(mockBar.Object).AreThereIntegers());
    }

    public interface IBar
    {
        IEnumerable<int> Integers { get; }
    }

    public class Foo
    {
        private IBar _bar;

        public Foo(IBar bar)
        {
            _bar = bar;
        }

        public bool AreThereIntegers()
        {
            return _bar.Integers.Any();
        }
    }
}

运行时无法初始化模拟

Test method NoIntegers threw exception: System.NotSupportedException: Expression references a method that does not belong to the mocked object: x => x.Any<Int32>()

我尝试以几种形式添加It.IsAny()

mockIntegers
    .Setup(x => x.Any(It.IsAny<IEnumerable<int>>(), It.IsAny<Func<int, bool>>()))
    .Returns(false);

// No method with this signiture


mockIntegers
    .Setup(x => x.Any(It.IsAny<Func<int, bool>>()))
    .Returns(false);

// Throws: Test method NoIntegers threw exception: 
// System.NotSupportedException: 
// Expression references a method that does not belong to the mocked object:
//  x => x.Any<Int32>(It.IsAny<Func`2>())

我需要模拟什么才能运行它?

【问题讨论】:

    标签: c# .net unit-testing mocking moq


    【解决方案1】:

    已修复!

    不漂亮,但这是需要的嘲笑:

       [TestMethod]
        public void NoIntegers()
        {
            Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
            Mock<IEnumerable<int>> mockIntegers = new Mock<IEnumerable<int>>(MockBehavior.Strict);
            Mock<IEnumerator<int>> mockEnumerator = new Mock<IEnumerator<int>>(MockBehavior.Strict);
            mockBar
                .SetupGet(x => x.Integers)
                .Returns(mockIntegers.Object);
    
            mockIntegers
                .Setup(x => x.GetEnumerator())
                .Returns(mockEnumerator.Object);
    
            mockEnumerator.Setup(x => x.MoveNext()).Returns(false);
    
            mockEnumerator.Setup(x => x.Dispose());
    
            Assert.IsFalse(new Foo(mockBar.Object).AreThereIntegers());
        }
    
        public interface IBar
        {
            IEnumerable<int> Integers { get; }
        }
    
        public class Foo
        {
            private IBar _bar;
    
            public Foo(IBar bar)
            {
                _bar = bar;
            }
    
            public bool AreThereIntegers()
            {
                return _bar.Integers.Any();
            }
        }
    

    【讨论】:

    • +1,即使在接受另一个答案后也能跟进。这个解决方案对我没有被接受的答案很有帮助。
    【解决方案2】:

    您只需要模拟 Integers 属性。没有必要模拟Any()(无论如何你都不能这样做,因为它是一种扩展方法),因为它是SUT 的一部分。对于两种情况,您应该这样做:

    [TestMethod]
    public void NoIntegers()
    {
        Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
    
        mockBar.SetupGet(x => x.Integers)
               .Returns(new List<int>());
    
        Assert.IsFalse(new Foo(mockBar.Object).AreThereIntegers());
    }
    
    [TestMethod]
    public void HasIntegers()
    {
        Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
    
        mockBar.SetupGet(x => x.Integers)
               .Returns(new List<int>{ 3, 5, 6});
    
        Assert.IsTrue(new Foo(mockBar.Object).AreThereIntegers());
    }
    

    【讨论】:

    • 返回一个具体类的问题是我不能断言它没有任何变化。不过它更整洁。
    • @BanksySan 你不需要测试和模拟一切。 .NET BCL 是一个稳定的依赖项,您必须假设它可以正常工作并测试您自己的代码。
    • 我知道不要测试框架,我的意思是应用程序代码。实际代码比我提供的示例代码大,我想断言枚举中的对象没有任何变化。
    • @BanksySan 你可以从模拟中返回一个ReadOnlyCollection 实例。如果集合被修改并且您的测试将失败,它将引发异常。
    • IEnumerable 也是只读的,但这并不意味着其中的对象是不可变的,它们仍然可以更改属性...但是,我已经找到了您的解决方案。它勾选了所有方框,并且更容易阅读。
    【解决方案3】:

    它不起作用是因为Any()方法不是直接被IEnumerable&lt;T&gt;接口暴露出来的,而是定义为an extension method on Enumerable

    我认为您不能在任何模拟上设置对Any() 的调用,因为它本质上是一个静态方法。

    在这种情况下,我认为最好使用 IEnumerable&lt;int&gt; 的实例(例如:一个 int 数组),该实例可以设置为空/非空,具体取决于您要测试的内容。

    【讨论】:

    • 是的,静态是问题所在。被错误信息误导了。
    猜你喜欢
    • 2011-12-25
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多