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

本文介绍使用Moq来Mock方法.

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

Mock 对象

紧接着上文中的例子. 上一篇文章, 我在单元测试的时候, 把依赖项设为null:

然后便出现了NullReferenceException, 导致测试无法正常运行.

首先应该做的是在TransferApproval的构造函数里判断参数是否为null, 如果为null的话应该抛出ArgumentNullException:

这是更恰当的异常.

这样的话, 在测试的时候, 抛出的就是ArgumentNullException了, 它可以更恰当的表达程序出现的问题:

现在我们可以使用mock版本的依赖项来代替null了:

上面的代码首先使用Moq创建了一个mock版本的IPhysicalExamination的实例.

而由于Moq对依赖项进行了包装, 所以要获得实际的mock依赖项, 我们需要使用mockExamination.Object属性. 而这个属性的类型就是IPhysicalExamination.

另外一个测试方法我也这么改一下, 然乎重新Build. Run All Tests:

还是红色的, 但现在是测试没通过, 并不是抛出异常.

测试没通过的意思就是期待值和实际返回值不符.

让我们来调试一下这个测试, 我在TransferApproval类里面设置一个端点, 查看一下这个mock依赖项的方法返回值:

然后调试测试:

跑到断点

可以看到这个Mock版本依赖项的IsHealthy()方法的返回值是false.

我并没有对这个Mock版本的IPhysicalExamination的IsHealthy()方法设定返回值, 正因为如此, 它才会返回它方法返回类型的默认值, 它的返回类型是bool, 而bool的默认值是false, 所以现在IsHealthy()方法在没有设定的情况下的返回值就是false.

It类

而PhysicalExamination这个具体的实现类由于各种原因导致还没有实现, 为了让它不妨碍我们的单元测试, 我先设定让它在无论传进什么参数的情况下都会返回true.

从业务上来讲就是假设所有转会球员都可以通过体检:

那么现在所有的测试都应该可以通过了:

这里用到了It这个类, 在Moq里, It这个类是用来做参数匹配的, it 就是"它"的意思, 它就代表需要被匹配的参数.

It.IsAny<T>(), 它表示传递给方法的参数的类型只要是T就可以, 值是任意的. 只要满足了这个条件, 那么方法的返回值就是后边Returns()方法里设定的值.

Moq 关于It类的文档: http://www.nudoq.org/#!/Packages/Moq/Moq/It

它有下面几种用法:

  • Is<TValue>(Expression<Func<TValue, Boolean>>)
  • IsAny<TValue>()
  • IsIn<TValue>(IEnumerable<TValue>)
  • IsInRange<TValue>(TValue, TValue, Range)
  • IsNotIn<TValue>(IEnumerable<TValue>)
  • IsNotNull<TValue>()
  • IsRegex(string)

我认为通过方法名就可以知道这些方法的用途.

下面我修改一下该测试方法, 使用It其它几个方法:

其测试结果仍然是通过的.

严谨(Strict) vs 宽松(Loose) Mock

Moq里面有Strict(严谨)和Loose(宽松) mock对象的概念, 当然也有很多人不喜欢这个概念.

在当前的测试方法里, TransferApproval依赖于Mock<IPhysicalExamination>, 并调用其IsHealthy()方法.

如果不对IsHealthy()方法进行任何设定的情况下, 方法会返回bool的默认值false, 这种就是loose(宽松) Mock.

在创建Mock对象的时候, 还可选传递一个MockBehavior这个参数.

MockBehavior是一个枚举, 它有三个值:

  • MockBehavior.Strict, 如果mock对象上的方法没有被预先设置好, 那么测试中调用该方法的时候就会抛出异常.
  • MockBehavior.Loose, 即使方法没有被预先设置, 调用它的时候也不会抛出异常. 它会返回该方法返回类型的默认值.
  • MockBehavior.Default, 它代表MockBehavior.Loose.

如果上例使用Strict Mock, 那么将会抛出Exception:

下面我把一个测试改为Strict Mock, 并取消了对IsHealthy()方法的设置:

而测试时会抛出MockException:

在对方法进行设置后, 测试就会通过:

可以感觉到:

Loose Mock, 可以少写一些设定代码, 可以返回默认值, 不易让测试中断

Strict Mock, 需要写跟多的设定代码, 每个被调用的方法都需要进行设定, 所以也更容易让测试中断.

Moq的建议是: 大多数情况下应该使用Loose Mock, 只有特殊需要的时候才去使用Strict Mock.

out参数

修改一下TransferApproval类的转会审批方法:

这次使用的是带有out参数的IsHealthy()方法.

建立一个测试方法, 并设定这个带有out参数的方法:

很简单, 测试会通过:

完成的代码在: https://github.com/solenovex/Moq4-Tutorial-Code 02 After

未完待续....

使用 Moq 测试.NET Core 应用 -- Mock 方法相关推荐

  1. mock方法常用框架_什么是Mock测试?

    私底下接触到很多童鞋在问关于Mock测试的问题,今天就来一篇扫盲文. 在单元测试和接口测试过程中通常需要用到Mock测试,那么什么是Mock测试呢? mock 一词的英文翻译有模拟.虚拟的意思,所以M ...

  2. JUnit中测试异常抛出的方法

    最近在做TWU关于TDD的作业,对JUnit中测试异常抛出的方法进行了一些学习和思考. 在进行单元测试的时候有的时候需要测试某一方法是否抛出了正确的异常.例如,我有一个方法,里面对一个List进行读取 ...

  3. 单元测试与 Mock 方法

    Mock 方法是单元测试中常见的一种技术,它的主要作用是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与测试边界以外的对象隔离开. 编写自定义的 Mock 对象需要额外的编码工作,同时也可能 ...

  4. 高效的敏捷测试第十一课 敏捷测试分析、策略和方法

    第26讲:基于上下文驱动思维的测试分析 从这一讲开始,我们就进入了第 5 部分内容的学习:敏捷测试分析与计划.在这一部分你将学到:测试需求分析.测试风险的识别.测试策略及测试计划的制定.今天先从基于上 ...

  5. 同域内测试蠕虫的一种方法

    汗--本来在讨论这个的http://www.gnucitizen.org/blog/ghost-busters/,有意思: <a href="javascript:x=open('ht ...

  6. VS2010测试功能之旅:编码的UI测试(6)- 提高UI测试稳定性的8个方法(下)

    VS2010测试功能之旅 --编码的UI测试系列之六:提高UI测试稳定性的8个方法(下) RealZhao,2011年5月11日 回顾 在之前,我们介绍了提高UI测试稳定性的8个方法的前6个,接下来介 ...

  7. 【Groovy】Groovy 扩展方法 ( 实例扩展方法配置 | 扩展方法示例 | 编译实例扩展类 | 打包实例扩展类字节码到 jar 包中 | 测试使用 Thread 实例扩展方法 )

    文章目录 一.扩展方法示例 二.实例扩展方法配置 三.编译实例扩展类 四.打包静态扩展类字节码到 jar 包中 五.测试使用 Thread 实例扩展方法 一.扩展方法示例 为 Thread 扩展 he ...

  8. python编程django项目中ModuleNotFoundError: No module named ‘django.core.urlresolvers‘解决方法

    文章目录 遇到的问题 解决方法 参考 遇到的问题 在做<python编程-从入门到实践>书中的项目的时候,遇到No module named 'django.core.urlresolve ...

  9. DCMTK:测试DcmItem的newDicomElement()辅助方法

    DCMTK:测试DcmItem的newDicomElement辅助方法 测试DcmItem的newDicomElement()辅助方法 测试DcmItem的newDicomElement()辅助方法 ...

最新文章

  1. 5G NGC — 关键技术 — 网络切片 — 实现原理
  2. android gridview不显示 自定义,Android gridview和自定义标题
  3. Sql Server数据库数据导入到SQLite数据库中
  4. webpack使用教程 翻译自阮一峰(机翻)
  5. 人行二代征信报告模版_人行首度明确,替代数据纳入征信管理!美化信用报告,难了...
  6. Docker 私有仓库的搭建
  7. ArcGIS实验教程——实验八:矢量数据拼接
  8. NAR再版 | 人类长非编码RNA知识库LncRNAWiki 2.0
  9. C++编程中const和#define的区别
  10. 农民工兄弟学C#(4)
  11. 【CDAS峰会】吴喜之:数据科学的未来发展
  12. 集中式网络、分散式网络及分布式网络的概念、定义、差别 以及 多智能体一致性控制问题
  13. python第三方库 invalid requirement_python第三方库安装出问题
  14. ip a命令显示的UP与LOWER_UP的区别
  15. 英文双引号引发的杯具
  16. 在MySQL中,如何给用户授予权限
  17. 日序计算器(计算某日期在该年为第几天)
  18. iOS开发-技术知识盘点总结(二)
  19. 北邮考研复试机试准备过程(已上岸)
  20. XST综合、实现过程包含哪些步骤

热门文章

  1. 计算机更新80072f76,windows update 80072f76错误
  2. 使用svn进行本地代码管理
  3. Python----面试题(二)
  4. php_curl.dll libssh2.dll 始终无法加载的原因 及解决办法
  5. vc6项目-vc8项目 转换日志
  6. SQL Server 2005中的SQLCMD工具使用
  7. docker安装以及部署springboot项目
  8. pulsar常用命令
  9. layui表格固定列覆盖滚动条导致错位
  10. IDEA for win 常用快捷键