推荐单元测试新的模拟框架:Nsubstitute

目前,.NET已经有很多强大模拟框架,为什么还要再重新写一个呢?按照Nsubstitute的官方说法是:所有的模拟框架都已经有强大的功能,但是现存的框架当中,没有一个满足我们对更简洁语法风格的追求。

第一次看到Nsubstitute,是在看Nunit的源码时发现,实际上Nunit已经不推荐大家使用它原来的Mock框架,它引入了Nsubstitute。经了解,Nsubstitute已经是一个具有两年多历史的模拟框架,也算是比较年轻的框架,它昨天(2012-5-4)刚发布了1.4版本。模拟框架很多,我们的选择很多,但是从现在开始,我们可以考虑一下用Nsubstitute,多了一个选择。

1. Nsubstitute简介

它是一个开源的框架,源码是C#实现的。你可以在这里获得它的源码:https://github.com/nsubstitute/NSubstitute

NSubstitute 更注重替代(Substitute)概念。它的设计目标是提供一个优秀的测试替代的.NET模拟框架。它是一个模拟测试框架,用最简洁的语法,使得我们能够把更多的注意力放在测试工作,减轻我们的测试配置工作,以满足我们的测试需求,帮助完成测试工作。它提供最经常需要使用的测试功能,且易于使用,语句更符合自然语言,可读性更高。对于单元测试的新手或只专注于测试的开发人员,它具有简单、友好的语法,使用更少的lambda表达式来编写完美的测试程序。

NSubstitute 采用的是Arrange-Act-Assert测试模式,你只需要告诉它应该如何工作,然后断言你所期望接收到的请求,就大功告成了。因为你有更重要的代码要编写,而不是去考虑是需要一个Mock还是一个Stub。

对比Moq,NSubstitute 的语法比更简练。这里的主要目的并不是为了比较框架的优劣。

2. 如何获取Nsubstitute?

有两种获得Nsubstitute的方式:

一是通过NuGet或者OpenWrap工具在Vs2010上安装Nsubstitute。

二是通过下载Nsubstitute 组件(https://github.com/nsubstitute/nsubstitute/downloads ),然后在测试项目当中引用 NSubstitute.dll 文件。现在的最新版本是1.4。

3. 测试方法

可以创建接口的实例,并设定接口方法的返回值,供测试。

1) 定义一个最基本的计算器接口:

public interface ICalculator

{

int Add(int a, int b);

int Subtract(int a, int b);

}

2) 创建测试项目、及测试程序

3) 引用命名空间声明

首先,在C#测试源码文件添加命名空间引用

using NSubstitute。

4) 创建接口实例

calculator = Substitute.For<ICalculator>();

5) 设定替代对象的接口方法返回值

指定Add被调用时,传入参数值分别为1、2时,替代的返回值为3

calculator.Add(1, 2).Returns(3);

6) 断言

Assert.AreEqual(calculator.Add(1, 2), 3);

7) Received的使用

另外,我们还可以检验替代对象的指定场景是否被调用,而哪些场景没有被调用,例如:

calculator.Add(1, 2);

calculator.Received().Add(1, 2);

calculator.DidNotReceive().Add(5, 7);

如果场景在之前没有被调用,Received() 断言则会失败。

例如:calculator.Received().Add(2, 3);

我们将会发现测试异常的提示信息如下:

测试方法 Calculator.Tests.ICalculatorTest.AddTest 引发了异常:

NSubstitute.Exceptions.ReceivedCallsException: Expected to receive a call matching:

Add(2, 3)

Actually received no matching calls.

Received 1 non-matching call (non-matching arguments indicated with '*' characters):

Add(*1*, *2*)

NSubstitute支持设置参数返回值,并断言已经被调用。下面是更复杂的使用:

calculator.Add(10, -5);

calculator.Received().Add(10, Arg.Any<int>());//第二个参数的值为任一int类型的整数。

calculator.Received().Add(10, Arg.Is<int>(x => x < 0));//第二个参数的值必须是小于零,否则将报异常

我们还可以使用替代对象的参数匹配及通过Returns()方法得到一些更多的行为:

//定义第一个参数及第二个参数为任意整数,并且返回值为两个参数之和。

calculator.Add(Arg.Any<int>(), Arg.Any<int>()).Returns(x => (int)x[0] + (int)x[1]);

Assert.AreEqual(calculator.Add(5, 10), 15);

4. 测试对象属性及事件委托

1) 定义一个接口:

public interface IPerson

{

string Name { get; set; }

event EventHandler Sleep;

}

2) 创建测试项目、及测试程序

3) 引用NSubstitute.dll,并声明命名空间

首先,在C#测试源码文件添加命名空间引用

using NSubstitute。

4) 创建接口实例

target= Substitute.For<IPerson>();

5) 测试属性的读写操作

target.Name.Returns("小明");

//测试属性的读操作

Assert.AreEqual(target.Name, "小明");

//对属性进行写操作

target.Name = "王二";

Assert.AreEqual(target.Name, "王二");

还可以使用Returns()设置的多个返回值序列

target.Name.Returns("A", "B", "C");

Assert.AreEqual(target.Name, "A");

Assert.AreEqual(target.Name, "B");

Assert.AreEqual(target.Name, "C");

6) 测试事件

bool eventWasRaised = false;

//定义委托事件

target.Sleep += (sender, args) => eventWasRaised = true;

//触发事件

target.Sleep += Raise.Event();

//断言事件被触发

Assert.IsTrue(eventWasRaised);

转载于:https://www.cnblogs.com/jinglelin/archive/2012/05/05/2484743.html

推荐一个单元测试模拟框架:Nsubstitute相关推荐

  1. 推荐一个C++练手项目,面试也可用

    经常有人问我,C++初学阶段有哪些项目可以拿来练手? 我一般都会建议他们尝试去写一个单元测试框架.因为这个项目十分考验我们对C++基础语法的掌握度. 但是自己摸索容易出错和遗漏,所以给大家推荐下面这个 ...

  2. JUnit基础及第一个单元测试实例(JUnit3.8)

    JUnit基础及第一个单元测试实例(JUnit3.8) 单元测试 单元测试(unit testing) ,是指对软件中的最小可测试单元进行检查和验证. 单元测试不是为了证明您是对的,而是为了证明您没有 ...

  3. 给大家推荐一个.Net的混淆防反编译工具ConfuserEx

    给大家推荐一个.Net的混淆防反编译工具ConfuserEx. 由于项目中要用到.Net的混淆防反编译工具. 在网上找了很多.Net混淆或混淆防反编译工具,如.NET Reactor.Dotfusca ...

  4. 推荐一个 Java 实体映射工具 MapStruct

    声明: 1.DO(业务实体对象),DTO(数据传输对象). 2.我的代码中用到了 Lombok ,不了解的可以自行了解一下,了解的忽略这条就好. 在一个成熟的工程中,尤其是现在的分布式系统中,应用与应 ...

  5. 给大家推荐一个SQL好的站点

    ,给大家推荐一个SQL好的站点 http://sqlteam.com/default.asp ,外国站点,有不少很好的文章

  6. 推荐一个当前互联网很火的技术

    001 什么是 Spring Boot ? 解释一下:Spring Boot 可以构建一切.Spring Boot 设计之初就是为了最少的配置,最快的速度来启动和运行 Spring 项目.Spring ...

  7. 推荐一个学算法的 GitHub 项目

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 这个项目的名称不那么文雅,直接抛地址: https:// ...

  8. 化腐朽为神奇:推荐一个让算法动起来更好理解的学习项目!

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 今天给大家推荐一个化腐朽为神器的开源项目:Algorit ...

  9. 推荐一个在线json数据格式化网站

    json数据非常友好方便的处理: 推荐一个在线json数据格式化网站 http://json.parser.online.fr/ 转载于:https://www.cnblogs.com/cocoaji ...

最新文章

  1. java web 开发应用 ----过滤器
  2. dedecms织梦模板修改专题路径的方法
  3. Ubuntu 18.04上进行HyperLedger Fabric 1.2.0环境及链码安装、部署和测试
  4. 20160419 while练习,复习
  5. entity reference在views中的运用
  6. MySQL 服务器调优
  7. 常见的两个面试题以及面试的心态
  8. 学习ActiveMQ(一):安装与启动
  9. hdfs 指令_Hadoop Shell命令
  10. SpringBoot之HelloWorld
  11. javascript在IE下的格式问题
  12. 数据库学习一站式入门资料(纯干货)
  13. [个人笔记] origin学习 入门教程
  14. 【计算机毕业设计】小型OA系统设计与实现Springboot
  15. 移动硬盘如何合并磁盘
  16. c语言数组升序排列,数组输入各数之间用空格隔开,输出用空格隔开
  17. Tomcat服务器日志输出格式设置
  18. python里的demo是什么意思_软件中的“DEMO” 是什么意思?游戏中的“DEMO呢?
  19. matlab 空间方程,matlab - 如何从MNA方程组到MATLAB中的状态空间[A,B,C,D] mimo? - 堆栈内存溢出...
  20. datanode无法启动Block pool ID needed, but service not yet registered with NN

热门文章

  1. java开发 中台
  2. J2EE(一)——开发简单WEB服务器
  3. ThinkPHP URL模式和URL重写
  4. eclipse的remote search
  5. 快速深入一门语言的几个问题
  6. BMP图片魔法师KeyGen
  7. 微信-js sdk invalid signature签名错误 问题解决
  8. 解决:夜神模拟器连不上adb的问题
  9. Java中的异常和处理详解
  10. 解决mybatis中#{}导致的The error may involve defaultParameterMap的问题