zoukankan      html  css  js  c++  java
  • 使用 Moq 测试.NET Core 应用 -- Mock 属性

    第一篇文章, 关于Mock的概念介绍: https://www.cnblogs.com/cgzl/p/9294431.html

    第二篇文章, 关于方法Mock的介绍: https://www.cnblogs.com/cgzl/p/9300356.html

    本文介绍Moq的使用.

    使用的代码: https://github.com/solenovex/Moq4-Tutorial-Code 里面的 03 Before 部分.

    Mock属性

    属性是指 get set property.

    接着上文, 我在03 Before部分的代码里做了一些修改.

    首先IPhysicalExamination接口添加了IsMedicalRoomAvailable属性:

    其实现类:

    属性方法内依然没有做实现.

    添加的这个属性在业务上的意思就是体检室是否可以使用. 如果不可以使用的话, 那么球员的转会操作应该被推迟.

    所以还需要为转会结果枚举添加一个推迟:

    最后在转会审批逻辑里进行判断, 如果体检室不可用, 那么转会就被推迟:

    在单元测试里对属性进行mock非常的简单:

    这个测试也会通过的:

    递归Mock

    修改一下IPhysicalExamination接口, 形成一个多层嵌套的属性:

    IPhysicalExamination --> IMedicalRoom --> IMedicalRoomStatus --> IsAvailable.

    通过上面这一串来判断体检室是否可用.

    相应的实现类也要修改:

    转会审批方法里也要修改:

    而在单元测试的方法里, 肯定是报错的:

    按照正常的思路, 我们可能会这样做:

    就是从内到外一层一层的mock.

    这么做是没问题的, 测试也会通过:

    但是这样做很麻烦, 而Moq则提供了一种简单的方式来处理这种多层的/递归的mock:

    这样写即可. 测试同样会通过:

    为属性设置默认值

    但是, 问题来了, 我还有一些其它的单元测试方法, 它们也需要用到这个属性, 现在它们的状态是:

    有的测试失败是因为其MockBehavior是Strict的, 而其它的失败则是因为里面出现了NullReferenceException.

    针对这些情况, 我们可以这样设定:

    这样设置之后, 它会返回属性类型的默认值, 因为我没有设定返回值.

    虽然测试依然不通过, 这是因为逻辑上的问题, 而不会抛出异常:

    针对这种情况, 还有一种更好的办法. 我们可以为mock对象设定默认值:

    把DefaultValue的值设为DefaultValue.Mock.

    但是DefaultValue这个属性只对引用类型起作用(对值类型不起作用), 像这种递归的mock, 它会递归的创建所需的引用类型, 但是最后的IsAvailable这个值类型是不起作用的.

    测试:

    因为最后一层是bool类型的, 是值类型, 所以上面的设置不起作用, 返回的是false. 所以测试没通过.

    那我就把它改成string类型好了:

    审批方法:

    然后再调试测试:

    string是引用类型, 但是mock的值依然是null...??!!??

    这是因为string是一个sealed class, 而DefaultValue.Mock只对接口, 抽象类和非sealed的class起作用....

    不过测试仍然是可以通过的, 因为我改逻辑了:

    注意, 这个默认值只对宽松(Loose) mock, 起作用.针对Strict mock, 仍然需要设定最后一层属性的值.

    属性值变化跟踪

    需要添加一些代码, 首先添加一个枚举:

    为接口添加属性:

    实现类:

    然后在审批类里, 我设置了这个属性的值:

    上面的代码也就是说, 我的mock对象的某个属性在测试的时候它的值会发生变化. 而Moq可以记住这些mock属性的变化的值.....

    新写一个测试:

    这里使用mockObj.SetupProperty()方法来开始追踪属性. 这个测试会通过:

    该方法也可以通过下面的写法来为被追踪的属性设置默认值:

    mockExamination.SetupProperty(x => x.PhysicalGrade, PhysicalGrade.Failed);.

    如果这个对象上有很多属性需要进行设置和追踪, 那么可以使用:

    mock.SetupAllProperties(); 这个方法:

    注意, 这个方法应该最先调用, 否则的话其它的设置可能会被覆盖.

    本文完成的代码在: https://github.com/solenovex/Moq4-Tutorial-Code 里面的03 After.

    未完待续......

  • 相关阅读:
    ubuntu安装pgAdmin 4
    python 读取文件
    byobu copy
    vim快捷键汇总
    python 停止线程
    python执行外部命令并获取输出
    gevent mysql
    python类型转换
    量化交易
    Java集合:HashMap底层实现和原理(源码解析)
  • 原文地址:https://www.cnblogs.com/cgzl/p/9304567.html
Copyright © 2011-2022 走看看