• .net测试篇之Moq行为配置


    系列目录

    我们前面说过.Moq在创建模拟对象的时候,简单对象赋值默认值,引用对象赋值为null,但是有些时候接口里面还包含另一个接口对象,我们知道Moq是可以模拟一个接口对象的,我们可以通过配置让Moq模拟所有可以Mock的对象.

    我们新增如下代码

     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,我们便可以对其进行操作了.

    我们通过调试可以发现这时候不但IDtoWrapper不再是null,它里面的Dto属性也被赋值为一个new MyDto.是不是Mock框架可以模拟一个对象呢,实际上确实是可以,只不过是它模拟对象有很多限制,比如不能模拟不包含无参构造函数的对象,不能模拟不带virtual或者abstract的方法等.如果我们对模拟的对象的方法没有virual或者abstract修饰,这时候如果进行setup则会抛出异常.

    前面我们讲的如何通过配置使mock自动mock遇到到层级可Mock对象.这一节我们来看另一个问题.

    假如有这样一种场:要mock的接口里有一个Name属性,在业务层我们要根据这个Name决定进入switch的不同分支里面,但是回顾前面的章节,我们没有遇到这种情况,我们都是只是在mock对象建立时使用setup为要mock的对象的字段设置值.很多人可能会想,可以通过moq对象实体的Object属性把这个对象拿出来,然后改变它的值.我们来看看这样做可行不可行.

    我们有以下一个简单接口

      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,不幸的是,测试没有通过.

    Avatar

    按我们理解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它,而只需要给它重新赋值即可.

  • 相关阅读:
    从零开始学asyncio(中)
    从零开始学asyncio(上)
    Java 后台多次获取requestBody
    Swift中的构造器
    CIDetector 相册识别二维码出错
    Swift-类和结构体
    定时器的使用以及注意事项
    ios-视图控制器跳转时生命周期的调用
    使用NSString的一些注意事项
    CALayer的锚点
  • 原文地址:https://www.cnblogs.com/tylerzhou/p/11416041.html
Copyright © 2020-2023  润新知