在 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);

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

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

我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

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

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

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

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

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

  3. Python 的mock模拟测试介绍

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

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

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

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

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

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

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

  7. WPF 判断调用方法堆栈

    原文:WPF 判断调用方法堆栈 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee.io 访问博客 ...

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

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

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

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

随机推荐

  1. Inno Setup生成桌面快捷方式

    在做项目的时候,需要打包成exe安装包.先前使用的是vs来打包,生成了setup.exe 和 *.msi的安装文件,不过也算顺利. 后因为要求采取 Inno Setup来打包程序,其中遇到个创建快捷方 ...

  2. LRM-00109: could not open parameter file '/u01/app/oracle/product/12.1.0/db_1/dbs/initepps.ora'

    安装好oracle后,起动时报如下错误: [oracle@Oracle-A ~]$ export ORACLE_SID=ORCL [oracle@Oracle-A ~]$ sqlplus / as s ...

  3. 应用node-webkit(NWJS)把BS架构的网址封装成桌面应用

    一.目的 给WEB应用的用户提供一款同一的浏览器,访问固定网址,封装一些常用插件(如flash插件等) 二.步骤 1.下载node-webkit,官方网址https://nwjs.io/ 2.解压下载 ...

  4. 使用css制作三角

    1. 字符实现三角效果关于字符实现三角我早在09年的时候就介绍了:使用字符实现兼容性的圆角尖角效果.一转眼两年过去了,这个技术开始被越来越多的人所熟知.使用的字符是正棱形“◆”字符,编码表示为◆ . ...

  5. offsetheight 和clientheight、scrollheight、scrollTop区别

    clientHeight:元素客户区的大小,指的是元素内容及其边框所占据的空间大小(经过实践取出来的大多是视口大小) scrollHeight: 滚动大小,指的是包含滚动内容的元素大小(元素内容的总高 ...

  6. git 本地仓库操作

    一.git对象模型和存储 二.常用命令 1)git checkout branch 切换分支 假设现在有两个分支,master和dev分支 i dev分支上没有readme.txt 在master分支 ...

  7. 「BZOJ3505」[CQOI2014] 数三角形

    「BZOJ3505」[CQOI2014] 数三角形 这道题直接求不好做,考虑容斥,首先选出3个点不考虑是否合法的方案数为$C_{(n+1)*(m+1)}^{3}$,然后减去三点一线的个数就好了.显然不 ...

  8. 学习meta标签http-equiv属性

    meta标签http-equiv属性的使用:meta标签http-equiv属性的使用

  9. saltStack_Pillar

    Pillar是Salt非常重要的一个组件,它用于给特定的minion定义任何你需要的数据,这些数据可以被Salt的其他组件使用.这里可以看出Pillar的一个特点,Pillar数据是与特定minion ...

  10. mosquitto/openssl 在RK3288上的编译以及MQTT客户端的代码示例

    1,依赖库openssl 的交叉编译 (1)配置编译器信息 setarch i386 ./config no-asm shared --cross-compile-prefix=arm-linux-a ...