NSubstitute完全手册(一)入门基础

简介:

NSubstitute入门

最简单的入门方式就是创建一个测试项目,并将 NSubstitute 引用到其中。可以通过 NuGet 或OpenWrap 来获取 NSubstitute 包。也可以直接下载 NSubstitute 文件,然后将 NSubstitute.dll 引用到项目中。

然后就可以创建一个新的测试 Fixture(可以选择使用你最喜欢的UT测试框架,本文涉及的示例中我们使用MSTest),开始思考从哪里入手。

首先,添加 using NSubstitute; 到当前的C#代码文件中,有了它我们就可以开始创建替身了。

现在,比如我们有一个非常简单的计算器接口:

1     public interface ICalculator
2     {
3       int Add(int a, int b);
4       string Mode { get; set; }
5       event EventHandler PoweringUp;
6     }

我们可以让NSubstitute来创建类型实例的替代实例。可以创建诸如 Stub、Mock、Fake、Spy、Test Double 等,但当我们只是想要一个能有一定程度控制的替代实例时,为什么我们要困扰于此呢?

1     [TestMethod]
2     public void Test_GetStarted_GetSubstitute()
3     {
4       ICalculator calculator = Substitute.For<ICalculator>();
5     }

现在,我们可以告诉被创建的替代实例,当方法被调用时返回一个值:

复制代码
1     [TestMethod]
2     public void Test_GetStarted_ReturnSpecifiedValue()
3     {
4       ICalculator calculator = Substitute.For<ICalculator>();
5       calculator.Add(1, 2).Returns(3);
6 
7       int actual = calculator.Add(1, 2);
8       Assert.AreEqual<int>(3, actual);
9     }
复制代码

我们可以检查该替代实例是否接收到了一个指定的调用,或者未收到某指定调用:

复制代码
1     [TestMethod]
2     public void Test_GetStarted_ReceivedSpecificCall()
3     {
4       ICalculator calculator = Substitute.For<ICalculator>();
5       calculator.Add(1, 2);
6 
7       calculator.Received().Add(1, 2);
8       calculator.DidNotReceive().Add(5, 7);
9     }
复制代码

如果 Received() 断言失败,NSubstitute 会尝试给出有可能是什么问题:

复制代码
1     [TestMethod]
2     [ExpectedException(typeof(ReceivedCallsException))]
3     public void Test_GetStarted_DidNotReceivedSpecificCall()
4     {
5       ICalculator calculator = Substitute.For<ICalculator>();
6       calculator.Add(5, 7);
7 
8       calculator.Received().Add(1, 2);
9     }
复制代码
Expected to receive a call matching:
    Add(1, 2)
Actually received no matching calls.
Received 1 non-matching call (non-matching arguments indicated with '*' characters):
    Add(*5*, *7*)

我们也可以对属性使用与方法类似的 Retures() 语法,或者继续使用简单的属性 setter 来设置返回值。

复制代码
 1     [TestMethod]
 2     public void Test_GetStarted_SetPropertyValue()
 3     {
 4       ICalculator calculator = Substitute.For<ICalculator>();
 5 
 6       calculator.Mode.Returns("DEC");
 7       Assert.AreEqual<string>("DEC", calculator.Mode);
 8 
 9       calculator.Mode = "HEX";
10       Assert.AreEqual<string>("HEX", calculator.Mode);
11     }
复制代码

NSubstitute 支持参数匹配功能,可以设置参数规则,并断言判断是否接收到参数匹配的调用。

复制代码
 1     [TestMethod]
 2     public void Test_GetStarted_MatchArguments()
 3     {
 4       ICalculator calculator = Substitute.For<ICalculator>();
 5 
 6       calculator.Add(10, -5);
 7 
 8       calculator.Received().Add(10, Arg.Any<int>());
 9       calculator.Received().Add(10, Arg.Is<int>(x => x < 0));
10     }
复制代码

我们也可以在使用参数匹配功能的同时,传递一个函数给 Returns() ,以此来使替代实例具有更多的功能。

复制代码
 1     [TestMethod]
 2     public void Test_GetStarted_PassFuncToReturns()
 3     {
 4       ICalculator calculator = Substitute.For<ICalculator>();
 5       calculator
 6          .Add(Arg.Any<int>(), Arg.Any<int>())
 7          .Returns(x => (int)x[0] + (int)x[1]);
 8 
 9       int actual = calculator.Add(5, 10);
10 
11       Assert.AreEqual<int>(15, actual);
12     }
复制代码

Returns() 也可通过构造一个返回值序列来指定多个参数。

复制代码
 1     [TestMethod]
 2     public void Test_GetStarted_MultipleValues()
 3     {
 4       ICalculator calculator = Substitute.For<ICalculator>();
 5       calculator.Mode.Returns("HEX", "DEC", "BIN");
 6 
 7       Assert.AreEqual<string>("HEX", calculator.Mode);
 8       Assert.AreEqual<string>("DEC", calculator.Mode);
 9       Assert.AreEqual<string>("BIN", calculator.Mode);
10     }
复制代码

最后,我们可以在替代实例上引发事件通知:

复制代码
 1     [TestMethod]
 2     public void Test_GetStarted_RaiseEvents()
 3     {
 4       ICalculator calculator = Substitute.For<ICalculator>();
 5       bool eventWasRaised = false;
 6 
 7       calculator.PoweringUp += (sender, args) =>
 8       {
 9         eventWasRaised = true;
10       };
11 
12       calculator.PoweringUp += Raise.Event();
13 
14       Assert.IsTrue(eventWasRaised);
15     }
复制代码

基本上这些就是入门 NSubstitute 的全部内容。对于更详细的功能说明,以及一些 NSubstitute 所支持的不太常用的需求,请继续阅读

NSubstitute 完全手册





本文转自匠心十年博客园博客,原文链接:http://www.cnblogs.com/gaochundong/archive/2013/05/21/nsubstitute_get_started.html,如需转载请自行联系原作者
目录
相关文章
小白入门必备!计算机科学教程的Python精要参考PDF开放下载!
随着互联网产业的高速发展,在网络上早已积累了极其丰富的Python学习资料,任何人都可以基于这些资源,自学掌握 Python。 但实际上,网络上充斥的资源太多、太杂且不成体系,在没有足够的编程/工程经验之前,仅靠“看”线上资源自学,的确是一件非常困难的事。
|
7月前
编程笔记 01工具及参考资料
编程笔记 01工具及参考资料
|
存储 人工智能 算法
C++ Primer Plus 第6版 读书笔记(7)第 7 章 函数——C++的编程模块
乐趣在于发现。仔细研究,读者将在函数中找到乐趣。C++自带了一个包含函数的大型库(标准 ANSI 库加上多个 C++类),但真正的编程乐趣在于编写自己的函数;另一方面,要提高编程效率,本章和第 8 章介绍如何定义函数、给函数传递信息以及从函数那里获得信息。
168 0
|
Python 程序员
语法学习 | python从入门到精通:入门篇之四
本节将学习一些Python的的基本语法,包括变量、标识符、字面量等内容。
10247 0
语法学习 | python从入门到精通:入门篇之四
|
开发者 Python
怎样使用自定义模块? | 手把手教你入门Python之四十九
如果一个py文件要作为一个模块被别的代码使用,这个py文件的名字一定要遵守标识符的命名规则。
怎样使用自定义模块? | 手把手教你入门Python之四十九
|
开发者 Python
MarkDown语法的使用 | 手把手教你入门Python之四
上节课我们安装了Typora,它就是一个用来编辑笔记的软件,而且它支持的格式和语法是MD形式,这节课我们就来学习该语法的使用。
MarkDown语法的使用 | 手把手教你入门Python之四
|
索引 Python
列表中的方法简介 | Python从入门到精通:进阶篇之五
本文讲述了如何通过方法修改列表,包括添加元素、删除元素、列表的翻转以及排序等的使用方式。
列表中的方法简介 | Python从入门到精通:进阶篇之五
|
Web App开发 索引 Spring
第18章 附录 & 参考资料 《Kotin 编程思想·实战》
第18章 附录 & 参考资料 https://github.com/EasyKotlin/kotlin-in-action Awesome Kotlin: https://kotlin.
1252 0