系列目录html
咱们前面说过.Moq在建立模拟对象的时候,简单对象赋值默认值,引用对象赋值为null,可是有些时候接口里面还包含另外一个接口对象,咱们知道Moq是能够模拟一个接口对象的,咱们能够经过配置让Moq模拟全部能够Mock的对象.app
咱们新增以下代码框架
public interface IDtoWrapper { MyDto Dto { get; set; } string GetString(); } public interface IOutString { IDtoWrapper wrapper { get; set; } }
好比咱们要模拟一个IOutString对象,若是不使用默认的行为则里面的wrapper对象返回为Null,若是这样咱们无法再继续操做了.函数
咱们能够对Moq的Default
行为进行配置,让它对IDtoWrapper对象也进行Mock测试
测试代码以下调试
[Test] public void BehaviorConfig() { var moq = new Mock<IOutString>(); moq.DefaultValue = DefaultValue.Mock; Assert.NotNull(moq.Object.wrapper); }
以上测试会经过.这时候wrapper再也不是null,咱们即可以对其进行操做了.code
咱们经过调试能够发现这时候不但IDtoWrapper再也不是null,它里面的Dto属性也被赋值为一个new MyDto.是否是Mock框架能够模拟一个对象呢,实际上确实是能够,只不过是它模拟对象有不少限制,好比不能模拟不包含无参构造函数的对象,不能模拟不带virtual或者abstract的方法等.若是咱们对模拟的对象的方法没有virual或者abstract修饰,这时候若是进行setup则会抛出异常.htm
前面咱们讲的如何经过配置使mock自动mock遇到到层级可Mock对象.这一节咱们来看另外一个问题.对象
假若有这样一种场:要mock的接口里有一个Name属性,在业务层咱们要根据这个Name决定进入switch的不一样分支里面,可是回顾前面的章节,咱们没有遇到这种状况,咱们都是只是在mock对象创建时使用setup为要mock的对象的字段设置值.不少人可能会想,能够经过moq对象实体的Object属性把这个对象拿出来,而后改变它的值.咱们来看看这样作可行不可行.blog
咱们有如下一个简单接口
public interface ISt { string Name { get; set; } int Age { get; set; } }
测试方法以下
[Test] public void BehaviorConfig() { var moq = new Mock<ISt>(); var obj = moq.Object; obj.Name = "baidu"; Assert.NotNull(moq.Object.Name); }
咱们把moq的Object对象赋值给obj,而后经过obj改变Name值.咱们断言moq.Object.Name的值不为null,不幸的是,测试没有经过.
按咱们理解obj和moq.Object应该是引用类型,因此obj值的改变会引发moq.object值的改变,然而实际状况倒是咱们一旦把moq.Objectm赋值给了obj,它们之间便脱离了关系.看来这样是行不通的.
如何解决这个问题呢,其实moq实例对象里面有一个SetupProperty方法,咱们能够经过它来显示指定哪些属性会被跟踪,若是属性被跟踪,则它的变化就会被记录下来,而不像上面.
[Test] public void BehaviorConfig() { var moq = new Mock<ISt>(); moq.SetupProperty(a => a.Name); var obj = moq.Object; obj.Name = "baidu"; Assert.NotNull(moq.Object.Name); }
咱们多加了一行代码,测试即可以经过了.
可是若是属性不少,这样一行一行几乎重复的代码挺烦的,moq实例里面还有一个SetupAllProperties
方法,这样能够设置全部的属性都被跟踪.这样若是多条须要这个值,咱们便不须要每次都mock它,而只须要给它从新赋值便可.