c# - 继承自 IReadOnlyCollection 的模拟类

标签 c# mocking moq

我想模拟一个继承自 IReadOnlyCollection 的类。我编写了一些示例代码来演示我的问题。三个断言中有两个有效。

当我将模拟的 IRemainingSteps 转换为列表或使用 LINQ 时,列表为空。

请您解释一下我应该如何更改 GetEnumerator 的设置以允许所有三个断言通过。

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Moq;
using NUnit.Framework;

namespace BranchScript.UT
{
    [TestFixture]
    public class Steps
    {
        [Test]
        public void Test()
        {
            // Arrange
            string branchA = "branch a";
            string branchB = "branch b";

            var mockStep1 = new Mock<IRemainingStep>();
            mockStep1.Setup(x => x.StepNotes).Returns(branchA);

            var mockStep2 = new Mock<IRemainingStep>();
            mockStep2.Setup(x => x.StepNotes).Returns(branchB);

            var mockStep3 = new Mock<IRemainingStep>();
            mockStep3.Setup(x => x.StepNotes).Returns(branchA);

            var mockStep4 = new Mock<IRemainingStep>();
            mockStep4.Setup(x => x.StepNotes).Returns(branchB);

            List<IRemainingStep> mockStepList = new List<IRemainingStep>
            {
                mockStep1.Object,
                mockStep2.Object,
                mockStep3.Object,
                mockStep4.Object
            };

            var refs = new Mock<IRemainingSteps>(MockBehavior.Strict);
            refs.Setup(r => r.GetEnumerator()).Returns(mockStepList.GetEnumerator());
            refs.As<IEnumerable>().Setup(r => r.GetEnumerator()).Returns(mockStepList.GetEnumerator());

            var mockPlate = new Mock<IPlate>();
            mockPlate.Setup(x => x.RemainingSteps).Returns(refs.Object);

            // Assert
            Assert.AreEqual(branchA, mockPlate.Object.RemainingSteps.First().StepNotes); // Pass
            Assert.AreEqual(branchB, mockPlate.Object.RemainingSteps.Last().StepNotes); // Pass
            Assert.AreEqual(2, mockPlate.Object.RemainingSteps.Where(x => x.StepNotes == branchA).Count()); // Fail
        }
    }

    public interface IRemainingSteps : IReadOnlyCollection<IRemainingStep>
    {
    }

    public interface IRemainingStep : IStep
    {
    }

    public interface IStep
    {
        string StepNotes { get; }
    }

    public interface IPlate
    {
        IRemainingSteps RemainingSteps { get; }
    }
}

最佳答案

传回枚举器仅允许一次读取,因为它仅向前传送。

var refs = new Mock<IRemainingSteps>(MockBehavior.Strict);
refs.Setup(r => r.GetEnumerator()).Returns(mockStepList.GetEnumerator());
refs.As<IEnumerable>().Setup(r => r.GetEnumerator()).Returns(mockStepList.GetEnumerator());

但是如果模拟返回一个函数,它将允许重复调用枚举器

var refs = new Mock<IRemainingSteps>(MockBehavior.Strict);
refs.Setup(r => r.GetEnumerator()).Returns(() => mockStepList.GetEnumerator());
refs.As<IEnumerable>().Setup(r => r.GetEnumerator()).Returns(() => mockStepList.GetEnumerator());

注意Returns中函数调用的使用

.Returns(() => mockStepList.GetEnumerator())

前两个断言有效,因为您仍在枚举器中前进。

Assert.AreEqual(branchA, mockPlate.Object.RemainingSteps.First().StepNotes); // Pass
Assert.AreEqual(branchB, mockPlate.Object.RemainingSteps.Last().StepNotes); // Pass

通过第三个断言,指针已经位于末尾

Assert.AreEqual(2, mockPlate.Object.RemainingSteps.Where(x => x.StepNotes == branchA).Count()); // Fail

因此计数不会如预期。

关于c# - 继承自 IReadOnlyCollection 的模拟类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57173297/

相关文章:

testing - 默认情况下将 Moq CallBase 设置为 true

c# - 为什么在使用 MSpec/Moq 测试此异步方法时会出现 NullReferenceException?

c# - Wpf 绝对与相对包 URI

c# - C#中如何处理大量数据?

python - 如何使用 Python MonkeyPatch + Mock 来断言调用了一个函数

java - 用于 TDD 的假 android 库

c# - 最小起订量混淆 - Setup() v Setup<>()

c# - 如何在 FluentValidation 中添加非属性规则?

c# - 如何转换 AS400 ADO.Net 连接字符串中的 CCSID 65535 个字符

java - 静态方法是 DI 反模式吗?