什么是Mock

当对代码进行测试的时候, 我们经常需要用到一些模拟(mock)技术.

绿色的是需要被测试的类, 黄色是它的依赖项, 灰色的无关的类

在一个项目里, 我们经常需要把某一部分程序独立出来以便我们可以对这部分进行测试. 这就要求我们不要考虑项目其余部分的复杂性, 我们只想关注需要被测试的那部分. 这里就需要用到模拟(Mock)技术.

因为, 请仔细看. 我们想要隔离测试的这部分代码对外部有一个或者多个依赖. 所以编写测试代码的时候, 我们需要提供这些依赖. 而针对隔离测试, 并不应该使用生产时用的依赖项, 所以我们使用模拟版本的依赖项, 这些模拟版依赖项只能用于测试时, 它们会使隔离更加容易.

绿色的是需要被测试的类, 黄色Mock的依赖项

Mock技术带来的优点

使用Mock技术, 可以有如下的优点:

  • 提高测试运行速度, 例如可以模拟DB, Web Service等比较慢的服务, 以及算法等.
  • 支持并行开发, 例如实际的依赖项还没有完成开发, 或者等待其他团队开发依赖项.
  • 提高测试可靠性, 例如有时这个依赖项的bug太多了, 经常由于依赖项的原因导致测试失败, 那么就应该使用mock版本来验证我们自己写的代码.
  • 减少开发/测试成本, 有时程序可能依赖一些云服务, 这些服务是按调用次数收费的, 那么就可以使用Mock版本来节省这方面的开资, 当然了最后还是需要使用真正的服务测试才行; 有时候组建依赖项太费劲了, 就用mock版本吧, 省时省力.
  • 在有不确定性依赖项的情况下进行测试, 有些依赖项有不确定性, 可能无理由的造成测试失败, 这时候就应该使用mock版本的依赖.

单元测试

Mock技术通常在单元测试中使用, 可以使用xUnit来为.NET Core应用做单元测试, 这里有介绍xUnit的文章: https://www.cnblogs.com/cgzl/p/9178672.html#xunit

那么什么是一个单元?

这个通常是由团队对系统的理解决定, 可以针对一个类, 也可以针对多个类.

单元测试通常具有以下特点:

  • 低级别
  • 高聚焦
  • 执行速度快
  • 容易测试所有执行路径上的代码

术语

  • Test Double (我认为可以翻译为测试替身), 是所有非真实依赖项的总称.

    • Fake, Fake是那种可以正常工作的实现, 尽管可以正常工作, 但是它们不可以用于生产环境, 例如EFCore里的内存数据库提供商.
    • Dummy, 有时候, 被测试方法需要一些参数, 但是这些参数实际上并没有用到, 这时就可以创建dummy, 它们的存在只是为了满足调用方法的参数要求.
    • Stub, (状态测试). 它可以使用很直接的方式模拟依赖项的行为. 例如我们可以使用Stub把相关数据放到内存里查询而不是查询真实的数据库; 如果某个测试类需要依赖项的某个Property的值, 那么stub就设定这个值就行.
    • Mock, (行为/交互测试). 与Stub不同的是, Mock期待的不是返回值, Mock期待的是动作的执行. 它是依赖项的动态包装, 它可以对哪个方法以什么样的顺序被待测试系统(SUT)调用的这个期待行为进行预编程. 也就是说被测试的系统只有按照特定的顺序调用mock依赖项的特定方法, 那么该系统才算测试通过.

还有其它的一些术语就不介绍了, 主要是这四个.

对于Stub 和 Mock ,可以看下面两张图例:

Moq

官网: https://github.com/moq/moq4

Moq框架可以用来创建dummy, stub 和 mock. 在本文里把这三个东西都叫做mock对象吧.

Moq使用一套API来创建stub和mock对象.

准备项目

一个简单的.NET Core控制台项目: https://github.com/solenovex/Moq-Tutorial-Code, 代码是里面的01 before.

该项目非常简单, 是关于球员转会业务, 它目前只有三个类.

TransferApplication, 球员转会申请类:

TransferResult, 转会审批结果枚举:

还有TransferApproval, 转会审批类:

'

当前的逻辑是, 发起球员转会申请后, 进行审批: 如果总费用大于预算, 那么就直接拒绝; 如果总费用不超标, 并且球员小于30岁, 那么就批准; 但如果球员大于30岁, 并且是超级巨星的话, 这将由老板决定.

建立单元测试项目

在解决方案里建立一个xUnit类型的项目:

然后要保证该项目所用到的库都保持最新:

最后别忘了添加对FootballManager项目的引用:

打开Text Explorer, 可以看到里面有一个待测的单元测试:

做一个简单的单元测试

把UnitTest1改成下面这个简单的单元测试:

重新Build后, 可以看到单元测试的名称更新了.

点击Run All, 运行单元测试, 结果成功:

随后再添加一个简单的单元测试:

Build, 后就会出现这个测试:

Run All, 测试也会成功:

添加依赖

这时, 有一些需求的变化, 球员转会审批前, 需要通过体检.

首先在转会申请类里面添加两个球员的属性:

然后添加一个体检的接口:

这两个方法的作用是一样的, 但是调用方法略有不同.

但是此时, 该接口的实现类还没有开发完毕:

在转会审批类里面, 需要添加这个依赖, 使用的是接口:

在单元测试类里面, 我为转会球员添加了这两个属性, 但是审批类会报错, 因为没有加入依赖项:

所以测试的时候需要注入这个依赖项IPhysicalExamination, 但是PhysicalExamination类还没有做完(里面的方法都没有实现), 所以我们无法new出来这个类.

这时, 我们也许可以传null进去?

这时, 项目是不报错了.

跑单元测试, Run All:

测试失败, 抛出NullReferenceException. 而这个异常导致了测试无法正常进行.

所以, 我们需要Moq, 它可以提供一个Mock(模拟)版本的IPhysicalExamination, 并把它传递到审批类的构造函数里.

安装Moq

在单元测试项目添加Moq:

Moq的第一篇先到这.

使用 Moq 测试.NET Core 应用 - Why Moq?的更多相关文章

  1. 使用 Moq 测试.NET Core 应用

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

  2. 使用 Moq 测试.NET Core 应用 -- 其它

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

  3. 使用 Moq 测试.NET Core 应用 -- Mock 方法

    第一篇文章, 关于Mock的概念介绍: https://www.cnblogs.com/cgzl/p/9294431.html 本文介绍使用Moq来Mock方法. 使用的代码: https://git ...

  4. 使用 Moq 测试.NET Core 应用 -- Mock 属性

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

  5. 使用 Moq 测试.NET Core 应用 -- Mock 行为

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

  6. Moq 测试 属性,常用方法

    RhinoMock入门(7)——Do,With和Record-playback 摘要: (一)Do(delegate)有时候在测试过程中只返回一个静态的值是不够的,在这种情况下,Do()方法可以用来在 ...

  7. Moq 在.net Core 单元测试中的使用

    Moq,主要用来伪造接口的实现类,实现方法,属性 moq The most popular and friendly mocking framework for .NET What? Moq (pro ...

  8. solr安装部署、solr测试创建core、用solrj 访问solr(索引和搜索)

    一.安装solr4.8: 1.把apache-solr-4.8.1\example\webapps下的solr.war文件拷贝到Tomcat下的Tomcat7.0\webapps目录下,tomcat启 ...

  9. 利用BenchmarkDotNet 测试 .Net Core API 同步和异步方法性能

    事由: 这两天mentor给我布置了个任务让我用BenchmarkDotNet工具去测试一下同一个API 用同步和异步方法写性能上有什么差别. 顺带提一下: 啊啊啊啊 等我仔细看文档的时候文档 发现它 ...

随机推荐

  1. 【转】linux系统中如何进入退出vim编辑器,方法及区别

    在linux家族中,vim编辑器是系统自带的文本编辑器,其功能强大自不必说了. 偶有小白,刚接触linux,要修改某个文本文件,不可能像WINDOWS那样操作,更有甚者,进入VI编辑器后,无法退出以致 ...

  2. CSS透明opacity和IE各版本透明度滤镜filter的准确用法

    滤镜名    说明 Alpha     让HTML元件呈现出透明的渐进效果Blur     让HTML元件产生风吹模糊的效果Chroma     让图像中的某一颜色变成透明色DropShadow    ...

  3. Java同步简介

    Java同步 Java中同步一直都是很重要的问题,对于初学者来说也是不太容易能理解的问题.特在此记录一下有关Java中同步和锁的知识.主要涉及到同步的概念以及Java中解决的办法和简单的例子.有关锁L ...

  4. 【强连通分量】Bzoj1654 [Usaco2006 Jan]The Cow Prom 奶牛舞会

    Description 约翰的N(2≤N≤10000)只奶牛非常兴奋,因为这是舞会之夜!她们穿上礼服和新鞋子,别上鲜花,她们要表演圆舞.     只有奶牛才能表演这种圆舞.圆舞需要一些绳索和一个圆形的 ...

  5. BZOJ_1503_[NOI2004]郁闷的出纳员_权值线段树

    BZOJ_1503_[NOI2004]郁闷的出纳员_权值线段树 Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的 工资. ...

  6. vue enter事件无效,加入native

    <Input type="password" v-model="password" placeholder="password" @k ...

  7. Sublime text3所遇到的问题

    sublime text3的下载地址:https://www.sublimetext.com/ 解决sublime text上不能使用交互的input的输入问题 通过安装sublimeREPL插件解决 ...

  8. Hadoop3.0 WordCount测试一直Accept 状态,Nodes of the cluster 页面node列表个数为0

    起因是我运行wordcount测试一直卡主,不能执行,一直处于 Accept 状态,等待被执行,刚开始是各种配置yarn参数,以及host配置,后来发现还是不行 hadoop 集群安装完成后,在500 ...

  9. 用node探究http缓存

    用node搞web服务和直接用tomcat.Apache做服务器不太一样, 很多工作都需要自己做.缓存策略也要自己选择,虽然有像koa-static,express.static这些东西可以用来管理静 ...

  10. Hyperledger Fabric、Corda和以太坊对比

     Hyperledger Fabric . Corda 和以太坊的对比 三种不同的框架 我们从 Hyperledger Fabric.R3 Corda和以太坊的白皮书中可以看到,三种框架在可能的应用领 ...