Moq,模拟一个抽象 class :模拟对象不能使用抽象 class 中实现的方法

Moq, mockin an abstract class : the mocked object does cannot use methods implemented in the abstract class

您好,我有一个类似于以下的代码:

        public abstract class MyAbstractClass
        {
            public virtual string DoSomething(string s1, string s2)
            {
                return this.DoSomethingElse(s1 + s2);
            }

            protected abstract string DoSomethingElse(string s);
        }


        [TestMethod]
        public void Test()
        {
            var myMock = new Mock<MyAbstractClass>();
            myMock.Protected().Setup<string>("DoSomethingElse", ItExpr.IsAny<string>()).Returns<string>(x => $"{x} I did it.");

            var result = myMock.Object.DoSomething("a", "b");

        }

我希望测试的结果是“ab I did it”,但我得到了一个空值。我注意到如果将“虚拟”删除到“DoSomething”方法,它会按预期 return。问题是我需要这个方法是虚拟的。老实说,根据我对最小起订量如何工作的理解,它应该 return “我做到了”,但也许我遗漏了什么。

有什么想法吗?谢谢

原因是因为您正在调用 DoSomething 方法 使用模拟对象 ,但是因为您没有告诉模拟对象使用真实的实现或者 Setup 它,默认情况下它只是“什么都不做”(即 return null)。

解决此问题的快速方法是为模拟对象设置 CallBase = true 属性。然后,任何不是 Setup 的方法都将使用真正的实现。

var myMock = new Mock<MyAbstractClass>() { CallBase = true };
myMock
    .Protected()
    .Setup<string>("DoSomethingElse", ItExpr.IsAny<string>())
    .Returns("DoSomethingElseResult");

Console.WriteLine("DoSomething: " + myMock.Object.DoSomething("a", "b"));

这将打印“DoSomething: DoSomethingElseResult”,这应该正是您想要的。模拟对象使用真实实现运行 DoSomething,而 DoSomething 的真实实现运行 DoSomethingElse.

的模拟实现