title author date CreateTime categories
dotnet 如何在 Mock 模拟 Func 判断调用次数
lindexi
2019-08-31 16:55:58 +0800
2019-5-28 15:3:36 +0800
dotnet

在 dotnet 程序有很好用的 Mock 框架,可以用来模拟各种接口和抽象类,可以用来测试某个注入接口的被调用次数和被调用时传入参数。本文告诉大家如何在 Mock 里面模拟一个 Func 同时模拟返回对象,获取调用次数

在 Mock 里面可以通过 Mock<Func<string>> 创建一个返回字符串的委托,通过 Setup 设置调试参数过滤和对应的模拟的返回值。如我期望模拟一个 Func 是 Func<int, string> 同时有要求传入的参数的值和想要在用户传入参数 0 的时候模拟返回值是 林德熙是逗比 如果用户传入的是其他的值,那么就不在意了

在 Mock 里面通过 Setup 可以说明如何进行模拟,写法是 Setup 里面调用的方法里面传入的参数就是说明当用户也传入什么参数的时候,在 Setup 返回值里面添加 Returns 方法说明如何返回

    mock.Setup(对象 => 对象.Xx方法(模拟用户传入的是什么参数)).Returns(模拟返回值);

如上面的需求可以这样写,在 Setup 里面调用 Func 传入参数 0 表示当用户传入参数 0 的时候执行什么,在后面的 Returns 方法是模拟返回值

 mock.Setup(func => func(0)).Returns("林德熙是逗比");

判断用户调用了模拟的方法多少次通过 Verify 方法,在 Verify 方法是调用模拟的方法,在模拟的方法传入参数指定在传入对应参数的时候,此方法调用了多少次

 mock.Verify(func => 对象.Xx方法(模拟用户传入的是什么参数), Times.Xx在传入什么参数的时候被调用了多少次);

例如当用户传入参数 0 的时候被调用一次可以这样写

 mock.Verify(func => func(0), Times.Once);

现在尝试写一个单元测试跑一下

        [ContractTestCase]
public void FooTests()
{
"当调用 Foo 时,将会传入 0 和 1 分别运行一次".Test(() =>
{
// Arrange
var mock = new Mock<Func<int, string>>();
mock.Setup(func => func(0)).Returns("林德熙是逗比"); // Action
Foo(mock.Object); // Assert
mock.Verify(func => func(1), Times.Once);
mock.Verify(func => func(0), Times.Once);
});
}

这个方式的单元测试是 MSTestEnhancer 提供的写法,可以将会写单元测试的理解和维护成本。传统的单元测试是要求命名的时候安装英文的规范命名,但是我的团队的小伙伴的英文都太渣了,要么就是太好了,反正我自己写的单元测试的方法命名我自己都看不懂。然而加上了 Display 特性用来显示中文的时候,依然存在的问题是需要自己想很久命名了一个自己也看不懂的单元测试名,然后在通过特性写一个中文,总体重复的工作量实在太多。而在 MSTestEnhancer 可以愉快使用中文的写法,直接在某个需要被测试的方法里面用字符串写明这个代码用来测试什么这样的代码将会比之前清真,写起来的代码量也少了很多

上面的代码还缺少一个被测试的 Foo 方法,现在写一下

        private void Foo(Func<int, string> func)
{
var str = func(1);
str = func(0);
}

此时的第一句调用 str = func(1) 返回的是空,因为没有定义,使用默认的返回值。第二句传入参数 0 返回值是 林德熙是逗比 因为上面定义

如上面代码写的,如果我期望定义的参数是一个范围而不是某个数,那么我需要采用 It 这个类的帮助

判断参数符合某个条件的任意参数,可以使用 Is 方法,如在传入任何的一个大于零的参数

  mock.Setup(func => func(It.Is<int>(n => n > 0))).Returns("林德熙是逗比");

这里可以使用的是委托,所以复杂的条件也可以自己写。另外 It 还提供很多其他的帮助方法,可以简化代码,这些自己写一下就知道

这里的 It 不仅可以在 Setup 使用,也可以在 Verify 方法使用,如判断用户传入小于0的参数的时候,这个方法被调用一次

 mock.Verify(func => func(It.Is<int>(n => n < 0)), Times.Once);

如果不要求传入的是什么参数,包括各种边界值都可能传入,那么请直接使用下面方法。下面代码表示传入的任意的 int 的参数就可以

 mock.Verify(func => func(It.IsAny<int>()), Times.Once);

另一个问题是判断调用次数,如果我期望的某个方法被调用两次如何写?

通过 Times.Exactly 可以指定某个方法就被调用某次

    mock.Verify(func => func(0), Times.Exactly(2));

表示这个方法重来没调用过可以使用 Never 请看代码

 mock.Verify(func => func(It.IsAny<int>()), Times.Never);

当然还有方法至少被调用多少次,方法最多被调用多少次等,这些很简单

我的小伙伴写了很多单元测试的博客,欢迎小伙伴访问

2019-8-31-dotnet-如何在-Mock-模拟-Func-判断调用次数的更多相关文章

  1. dotnet 如何在 Mock 模拟 Func 判断调用次数

    在 dotnet 程序有很好用的 Mock 框架,可以用来模拟各种接口和抽象类,可以用来测试某个注入接口的被调用次数和被调用时传入参数.本文告诉大家如何在 Mock 里面模拟一个 Func 同时模拟返 ...

  2. Mock 模拟测试简介及 Mockito 使用入门

    Mock 是什么mock 测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法.这个虚拟的对象就是mock对象.mock对象就是真实对象在调试期间的代 ...

  3. 深入浅出的webpack4构建工具---比mock模拟数据更简单的方式(二十一)

    如果想要了解mock模拟数据的话,请看这篇文章(https://www.cnblogs.com/tugenhua0707/p/9813122.html) 在实际应用场景中,总感觉mock数据比较麻烦, ...

  4. Python 的mock模拟测试介绍

    如何不靠耐心测试 可能我们正在写一个社交软件并且想测试一下"发布到Facebook的功能",但是我们不希望每次运行测试集的时候都发布到Facebook上. Python的unitt ...

  5. agentzh 的 Nginx 教程(版本 2019.07.31)

    agentzh 的 Nginx 教程(版本 2019.07.31) agentzh 的 Nginx 教程(版本 2019.07.31) https://openresty.org/download/a ...

  6. Mock模拟数据,前后端分离

    安装 使用npm安装: npm install mockjs; 或直接<script src="http://mockjs.com/dist/mock.js">< ...

  7. vue-cli实现异步请求返回mock模拟数据

    在前后端分离开发的过程中,前端开发过程中,页面的数据显示一般都是写死的静态数据,也就是没有经过接口,直接写死在代码中的,在后端给出接口后,再替换为接口数据,为了减少对接成本,mock就出现了.通过预先 ...

  8. [模拟回调] demo1模拟用字符串调用js函数 demo2模拟springmvc controller回调页面js函数

    demo1. 模拟用字符串调用js 函数 function dataQuery() { var strFun = "testCallBack"; var strParam = &q ...

  9. 使用Socket&反射&Java流操作进行方法的远程调用(模拟RPC远程调用)

    写在前面 阅读本文首先得具备基本的Socket.反射.Java流操作的基本API使用知识:否则本文你可能看不懂... 服务端的端口监听 进行远程调用,那就必须得有客户端和服务端.服务端负责提供服务,客 ...

  10. springboot2.0入门(四)----mock模拟测试+单元测试

    一.本节主要记录模拟测试.单元测试: 二.mock 测试 1.1什么是Mock? 在面向对象程序设计中,模拟对象(英语:mock object,也译作模仿对象)是以可控的方式模拟真实对象行为的假的对象 ...

随机推荐

  1. CSIC_716_20191105【数字、字符串、列表】

    python数据类型及其内置方法 一.整型:主要用于数学运算 其他进制----->转十进制 """ 其他进制转换为十进制 通过int('x进制数',x)实现 &qu ...

  2. python3和python2编码拾遗

    py2编码 tr和unicode str和unicode都是basestring的子类.严格意义上说,str其实是字节串,它是unicode经过编码后的字节组成的序列.对UTF-8编码的str'苑'使 ...

  3. pom parent 标签

    <!--parent用于引用父工程 1.统一管理jar包的版本,其依赖需要在子工程中定义才有效(比如此例) 2.统一的依赖管理(父工程的<dependencies>,子工程不必重新引 ...

  4. R语言 数据重塑

    R语言数据重塑 R语言中的数据重塑是关于改变数据被组织成行和列的方式. 大多数时间R语言中的数据处理是通过将输入数据作为数据帧来完成的. 很容易从数据帧的行和列中提取数据,但是在某些情况下,我们需要的 ...

  5. tomcat7 linux service

    1. 创建tomcat用户 useradd -r -m -d /usr/local/tomcat7 -s /sbin/nologin tomcat 2. 将下面脚本命名为tomcat7 放入/etc/ ...

  6. 牛客多校第六场 A Garbage 模拟/签到

    题意: 给你一个字符串,代表一个垃圾都有哪些物质组成,再给你一个字符串,代表a-z代表的物质分别是有害物质,干物质还是湿物质,根据题目的定义,回答是什么垃圾. 题解: 根据题意模拟即可. #inclu ...

  7. 基于UDP协议的套接字编程

    基于udp协议的套接字编程 UDP是无链接的,先启动那一端都不会报错 UDP协议是数据报协议,发空的时候也会自带报头,因此客户端输入空,服务端也能收到 一般不用与传输大数据 虽然没有粘包问题,但是不能 ...

  8. iOS之NSArray类簇简介-(copy、mutableCopy导致程序crash)

    1.前言 开发时常常用数组对数据进行处理,对NSMutableArray进行操作时经常导致程序崩溃,特研究一下NSArray的类簇!涉及__NSPlaceholderArray.__NSArray0. ...

  9. UVA 12412 A Typical Homework (a.k.a Shi Xiong Bang Bang Mang)

    题目链接:https://vjudge.net/problem/UVA-12412 题目大意 略. 分析 比较大规模的模拟,注意输入输出,浮点数精度,还有排名相同的输出顺序,还有一些边界情况处理. 代 ...

  10. 01_springboot2.x之springboot入门

    1.简介 Spring Boot来简化Spring应用开发,约定大于配置, 去繁从简,just run就能创建一个独立的,产品级别的应用. 优点: 1.简化Spring应用开发的一个框架: 2.整个S ...