当使用Moq来Mock一个具体的类,类里的方法为virtual时,Moq会将当前类,所有的virtual方法默认重写成空实现。
如果我们想要访问真实的代码,有两种方法
1、在创建Mock时,设置CallBack为True:则当前类里所有的方法全访问真实代码
var mock = new Mock<ChildClass>() { CallBase = true}; mock.Object.ChildDo();
2、只想单个访问真实代码,可以Setup此方法后,调用.CallBase()方法
mock.Setup(a => a.ChildDo()).CallBase();
-------------------------------------
当我们要监控父类里的虚方法时,这里有一个很恶心的地方:
如果子类里使用base.BaseDo()来调用父类的功能,父类的BaseDo方法无法被重写,也无法监控。
如果子类里使用this.BaseDo()或直接写BaseDo()来调用父类的功能,则父类的BaseDo方法会被重写,也可以监控。
public class BaseClass { public virtual void BaseDo() { throw new Exception("BaseDo");//检测时请屏蔽 } } public class ChildClass : BaseClass { public void ChildDo() { base.BaseDo();//不重写BaseDo方法,会throw,不能通过Verify检测 //this.BaseDo();//会重写BaseDo方法,不会throw,能通过Verify检测 } } [TestClass] public class Test { [TestMethod] public void Testing() { var mock = new Mock<ChildClass>(); mock.Object.ChildDo(); mock.Verify(a => a.BaseDo(), Times.Once); } }
我估计这么设计是因为是想严格判断是base里的还是this里的方法,这么一想还挺有道理,比如:
public class BaseClass { public virtual bool BaseDo() { return false; } } public class ChildClass : BaseClass { public override bool BaseDo() { return true; } public bool ChildDo() { return base.BaseDo();//不会监控 //return this.BaseDo();//会监控 } } [TestClass] public class Test { [TestMethod] public void Testing() { var mock = new Mock<ChildClass>(); var result = mock.Object.ChildDo(); mock.Verify(a => a.BaseDo(), Times.Once); } }
在这个例子里,base.BaseDo()和this.BaseDo()就是两个不同的方法,这时Moq判断的逻辑就更加清晰了
原则上,如果我们在代码里严格指定调用的是父类的方法(base.xxx()),那么Moq就不会去虚拟和监控父类的方法
-----------------------
参考资料:
https://www.cnblogs.com/haogj/archive/2011/07/22/2113496.html