惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Security Affairs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Jina AI
Jina AI
P
Palo Alto Networks Blog
GbyAI
GbyAI
大猫的无限游戏
大猫的无限游戏
A
Arctic Wolf
Hugging Face - Blog
Hugging Face - Blog
小众软件
小众软件
Y
Y Combinator Blog
T
The Blog of Author Tim Ferriss
Blog — PlanetScale
Blog — PlanetScale
S
Schneier on Security
V
Vulnerabilities – Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
雷峰网
雷峰网
T
Tenable Blog
人人都是产品经理
人人都是产品经理
T
Tor Project blog
C
Cyber Attacks, Cyber Crime and Cyber Security
AWS News Blog
AWS News Blog
Microsoft Security Blog
Microsoft Security Blog
J
Java Code Geeks
Scott Helme
Scott Helme
SecWiki News
SecWiki News
C
CERT Recently Published Vulnerability Notes
Recorded Future
Recorded Future
I
InfoQ
Security Archives - TechRepublic
Security Archives - TechRepublic
Help Net Security
Help Net Security
Cloudbric
Cloudbric
C
Check Point Blog
Engineering at Meta
Engineering at Meta
TaoSecurity Blog
TaoSecurity Blog
B
Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园_首页
N
News and Events Feed by Topic
云风的 BLOG
云风的 BLOG
MyScale Blog
MyScale Blog
腾讯CDC
量子位
Application and Cybersecurity Blog
Application and Cybersecurity Blog
K
Kaspersky official blog
Vercel News
Vercel News
F
Full Disclosure
T
Troy Hunt's Blog
Forbes - Security
Forbes - Security
S
Security @ Cisco Blogs

博客园 - 可乐加冰

QuickFIX/N与QuickFIX的.NET封装不同之处 QuickFIX/N入门:五、如何自定义FIX QuickFIX/N入门:四、使用消息循环分组 QuickFIX/N入门:三、 如何配置QuickFIX/N QuickFIX/N入门:二、发送消息及接收消息 QuickFIX/N入门:一、如何创建一个QuickFIX/N的应用程序 转、分享:PMP学习资料、考试资料推荐:第四版-2008版-吴永达 关于“类型初始值设定项引发异常” 浪费时间的主观原因 关于C#调用VC++.net程序集出现0x800736B1的异常 关于微软发布的Microsoft 图表控件 C#后期绑定方式来调用COM对象 Windows Mobile开发资源相关下载收录 值得珍藏的五十句话 Fund Managers Switching to Algorithmic Trading[转] winform窗体中嵌入显示Excel文件 让CheckBoxList,CheckBox 控件不能操作 - 可乐加冰 - 博客园 关于世界杯 C#在word文档中替换字符串
推荐一个单元测试模拟框架:Nsubstitute
可乐加冰 · 2012-05-05 · via 博客园 - 可乐加冰

推荐单元测试新的模拟框架: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

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

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被调用时,传入参数值分别为12时,替代返回值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);