从派生的 class 中起订基数 class 函数

Moq a base class function from a derived class

我是 Moq 的新手,我刚刚看了 Moqing 上的 pluralsight 视频,所以我觉得有能力去写一些测试。我有一个 Base Class 让我们说 Sheet 它实现了一个接口 ISheet。 Sheet 是页面的基础 class:

abstract class Sheet: ISheet
{
    public virtual void CreateSheet()  // Defined in ISheet
    {
    }
    public virtual void BuildSheet() // Defined in ISheet
    {
    }
    //and some abstract methods, etc.
}

public class Page : Sheet
{
    public override void CreateSheet()
    {
        BuildSheet(); // Base class implementation
    }
}

我覆盖了基础 class 中的一种方法,即 CreateSheet(),但我想测试调用基础 class 中的 BuildSheet() 方法从我派生的 class:

所以在我的测试中 Class,我 Moq SUT 而不是接口

var MockSheet = new Moq<Page>();

调用方法:

var actual = MockSheet.Object.CreateSheet(); 

然后验证

MockSheet.Verify(x => x.BuildSheet(), Times.AtLeastOnce);

相反,我得到 MockException “预期调用模拟至少一次,但从未执行过。 CreateSheet 方法永远不会被调用。如果我将他的 CreateSheet 方法更改为:

public void CreateDocSheet() // removed override
{
    BuildSheet() // base classses implementation
}

并在测试调用中:

var actual = MockSheet.Object.CreateDocSheet();  

有效。我不明白为什么。我相信从功能上讲,这是一种有效的编码方式,我有 sheet,它有 2 页,我有一个接口,它定义了所有应该实现的功能和属性,我在基础 class,但并非所有方法都需要在派生的 class 中实现,因此,一些方法被重写,一些使用基础 class 实现。请解释为什么使用函数的覆盖版本会出现问题?

Moq 用于模拟被测系统的一个或多个依赖项,以便您可以将其与应用程序的其余部分或外部性隔离开来,而不是用于替换被测系统.它不是您在此处尝试执行的操作的正确工具。

如果你改变

var MockSheet = new Moq<Page>();

进入

var MockSheet = new Moq<Page> { CallBase = true, };

您的模拟(您可以将其视为 Page 的派生 class)将在模拟自己的 CreateSheet 覆盖中从 Page 调用实现。

默认行为(如果您不更改 CallBase)是 Moq 覆盖每个方法并且 属性 它可以,并使用 empty 实施。将 CallBase 设置为 true 会使 Moq 调用 Page 实现,就像我说的那样。

(当然,如果你想让CreateDocSheet做一些不平凡的事,就用MockSheet.Setup(x => x.CreateDocSheet()).Callback(() => { /* something */ })。)

在您从 CreateSheet 中删除 virtual 修饰符的情况下,Moq 无法再覆盖或 mock 此成员。想一想:Moq "mock" 怎么可能是非虚拟方法?因此,该调用完全绕过了 Moq 的 class。