Fork me on GitHub
NSubstitute完全手册1

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 所支持的不太常用的需求,请继续阅读。

 

 
 
 
标签: C#.NETUnit TestingUTNSubstituteStubMockTest Double

STSdb,最强纯C#开源NoSQL和虚拟文件系统

回顾

几个月前写了一篇文章,关于 C#写的NoSQL开源项目/系统(系列),看过该文章的同学,估计会对.NET能实现高效的NoSQL是有信心的。几个月过去了,有了新进展。

 

STSdb是什么

再来说明一下STSdb是什么:STSdb是C#写的开源数据库和虚拟文件系统,支持实时索引,性能是同类产品的几倍到几十倍,访问官方网站

 

特性

  • 支持几十亿级别的数据存取
  • 支持TB级别文件大小
  • 实时索引
  • 内置压缩
  • 内置序列化
  • 支持稀疏分散的文件(byte[])

 

为什么?

数据库的共同点

 

每个数据库都有一个共同点,就是受限于索引结构,因此每当改进了索引数据结构,性能也随之大增。

 

性能瓶颈

 

在数据库系统中,每当对数据进行索引,数据的逻辑位置会被映射到物理设备,这个映射严重依赖设备的寻址时间。

 

解决办法

当遇到性能瓶颈时:

 

办法就是,不对每个操作都进行一次寻址,而是每次寻址都做多个操作。

 

 

解决方案-WATERFALLTREE™ (瀑布树)

STSdb 4.0突破性地发现并实现了Waterfall-tree (瀑布树)树结构。Waterfall-tree是注册商标,并且拥有专利。与传统的B+树类似,但B+树是同步操作,而瀑布树是分组异步操作。

现有的解决方案有一个共同的缺点:当索引随机主键的时候,I/O性能不高(退化严重)。

而STSdb4.0的瀑布树带了来前所未有的性能提升。

下图直观地展示了瀑布树的原理:

 

 

 

性能比较

 

数据库存储设计
Amazon Dynamo DB Zero-Hop Distributed Hash Table
Cassandra Memtable / SSTable
Couch DB Append-only B-tree
Db4objects B-tree
Google Big Table SSTable (log-structured storage)
H base Memtable / SSTable on HDFS
Level DB LSM-tree
Memcached Memory caching
Mongo DB B-tree
Oracle Berkeley DB B+-tree
Perst B-tree/T-tree/R-tree/Patricia trie/KD-tree
Redis In-memory only with background snapshots
Scalaris In-memory only
Tokyo Cabinet Hash or B-tree

 

 

随机写

 

随机读

 

顺序写

 

顺序读

 

这个性能,只能用凶残来形容啊!

 

应用领域

 

 

 

Hello STSdb

打开数据库并写入数据

using (StorageEngine engine = new StorageEngine("stsdb4.sys", "stsdb4.dat"))
{
    XIndex<int, string> table = engine.OpenXIndex<int, string>("table");
  
    for (int i = 0; i < 1000000; i++)
    {
        table[i] = i.ToString();
    }
  
    table.Flush();
    engine.Commit();
}

 

读取数据

using (StorageEngine engine = new StorageEngine("stsdb4.sys", "stsdb4.dat"))
{
    XIndex<int, string> table = engine.OpenXIndex<int, string>("table");
  
    foreach (var row in table) //table.Forward(), table.Backward()
    {
        Console.WriteLine("{0} {1}", row.Key, row.Value);
    }
}

 

更多例子

可以访问这里查看更多的例子,或者下载类库或代码,里面有pdf文档。

 

 

 
 
标签: stsdb
posted on 2013-05-21 22:20  HackerVirus  阅读(299)  评论(0编辑  收藏  举报