我是Moq的新手,我刚观看了莫青的复数视频,所以我觉得有权去写一些测试。我有一个基类让我们说Sheet实现了一个接口ISheet。 Sheet是页面的基类:
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
}
}
我覆盖了基类CreateSheet()
中的一个方法,但我想测试基类中的BuildSheet()
方法是从派生类中调用的:
所以在我的测试类中,我是SQ而不是接口
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();
有效。我不明白为什么。我相信在功能上这是一种有效的编码方式,我有工作表,有两页,我有一个接口,定义了应该实现的所有功能和属性,我在基类中实现这些功能,但不是全部方法需要在派生类中实现,因此,某些方法被覆盖,有些方法使用基类实现。请解释为什么使用重写版本的函数是一个问题?
答案 0 :(得分:8)
如果你改变了
var MockSheet = new Moq<Page>();
到
var MockSheet = new Moq<Page> { CallBase = true, };
你的模拟(您可以将其视为Page
的派生类)将在模拟自己的Page
覆盖中调用CreateSheet
中的实现。
默认行为(如果您不更改CallBase
)是Moq可以覆盖它可以覆盖的每个方法和属性,并使用 空 实现。将CallBase
设置为true
会使Moq调用Page
实现,就像我说的那样。
(当然,如果您希望MockSheet.Setup(x => x.CreateDocSheet()).Callback(() => { /* something */ })
做一些非平凡的事情,请使用CreateDocSheet
。)
如果您从virtual
删除CreateSheet
修饰符,则Moq无法再覆盖或模拟此成员。想一想:Moq如何“模拟”非虚拟方法?因此,这个电话完全绕过了Moq的课程。
答案 1 :(得分:7)
Moq用于模拟被测系统的依赖关系或依赖关系,以便您可以将其与其他应用程序或外部因素隔离,而不是替换您测试的系统。它不适合你在这里做的事情。