.Net单元测试之NMock

.Net单元测试之NMock

NMock是一款.NET平台下的基于动态代理的Mock模拟对象类库,用于C#开发。Mock对象使测试更简单,它测试单个组件或单个类时不需要其它所有组件真正实现。也就是说我们可以仅仅只是测试一个类,NMock生成的模拟是通过在运行时使用动态代理来实现的,这允许模拟对象动态的定义,并不需要添加任何附加的类。         通常,一个模拟的实现基于被依赖的接口而创建;NMock支持对接口和类的模拟,另外它还支持属性模拟。比起测试一个完整的对象关系树更容易查清楚Bug。Mock对象一般用于以测试为驱动的开发当中。

  • 为什么需要Mock

单元测试的基本原则应该是每次只验证一个方法,但是倘若遇到这样一种情况:

测试方法依赖于其他一些难以操控的东西,如:网络,数据库。或者是你测试的代码依赖于系统的其他部分,甚至是系统的多个其他部分。在这种情况下,倘若不小心,最终可能发现自己不小心几乎初始化了系统的每一个组件,而所有这一切只是为了给某一个测试创造必要的运行环境。这不仅花费了大量的时间,要命的是这样的测试用例会被引入大量的耦合因素,很难到达“单元”测试的目的。我们该怎么办呢? 这是Mock的测试方法就派上用场了。Mock的英文的字面意思是:嘲笑,模仿,欺骗的意思。通过Mock,我们可以创建很多真实对象的替代品,在测试用例中使用它。

  • 什么情况下考虑使用Mock

1)        真实的对象具有不可确定的行为(如:程序需要通过web service获得股票的实时价格)

2)        对象很难被创建(如系统环境很难初始化)

3)        真实对象的某些行为很难被触发(如网络错误,数据库ID自增序列溢出)

4)        真实的对象令程序运行很缓慢

5)        真实对象含有UI等不方便测试的因素

6)        测试需要询问真实对象是如何被调用的(如异步调用的情况,需要验证Callbak的函数)

7)        真实的对象目前还不存在(如依赖于其他项目组或则需要新的硬件系统)

  • 进行Mock测试的步骤
  • 测试代码首先引用NMock的框架

1)       定义一个接口来描述这个对象

2)        产品代码实现这个接口

3)        测试中Mock对象实现这个接口

下面是一个使用NMock的快速教程:

示例 现在我们来做一个简单的“Hello”例子,测试 Hello 类的 Greet() 方法,Hello 类依赖于一个 Person 对象,并将根据 Person 的名字向对应的账号发送祝贺(Greet)。这个例子很简单,其实用不到模拟对象,不过用来理解 NMock 是很合适的。

public interface IPerson {     string Name { get; } }

然后定义具有 Greet 方法的 Hello 类,可以根据 IPerson 的名字发送祝贺信息。

public class Hello {     IPerson person;     public Hello(IPerson person)     {         this.person = person;     }     public String Greet()     {         return "Hello " + person.Name;     } }

我们可以看到,Hello 类对 IPerson 接口有依赖。

在我们继续对 Hello 类的开发之前,让我们来学习一些关于 NMock 的基础知识。使用 NMock 很容易根据一个给定的接口或类来创建一个模拟对象;

1)首先你要实例化一个 Mock 对象,构建时要将你要模拟的接口或类的类型传递给 Mock 对象作为构建参数;

2)然后,你需要记录 Mock 对象的行为并最终通过 Mock 对象的属性来获得一个模拟类型的示例。下面是一个最简单的窗体的模拟对象,该模拟对象基于 IPerson 接口创建,没有记录任何行为。

        //通知 NMock 你在模拟哪个接口或类 IMock mockPerson = new DynamicMock(typeof(IPerson)); //获取指定类型的一个模拟实例 IPerson person = (IPerson) mockPerson.MockInstance;

然而如果我们不记录模拟对象应该做些什么或者在它使用之前需要做一些什么处理,那么实际上这个模拟对象是毫无用处的;在下面的例子中,我们将记录并设置 IPerson 的 Name 属性的值。

       //通知 NMock 你在模拟哪个接口或类 IMock mockPerson = new DynamicMock(typeof(IPerson));

        //设置值 mockPerson.ExpectAndReturn("Name", "John"); //获取指定类型的一个模拟实例 IPerson person = (IPerson) mockPerson.MockInstance;

NMock 有一个很长的很有用的 Expect 方法列表,使用这些列表我们可以设置模拟对象的行为,比如方法 A 被调用则返回 B,或者仅当用参数 C 调用方法 A 时才返回 B,或者当 A 方法被调用时则抛出异常 E,甚至我们可以告诉模拟对象它根本就不要指望能够调用方法 A。以上的简单例子表明我们希望 Name 属性只应该被调用一次,并且存取该属性时将返回字符串“John”;注意我们希望 Name 属性只应该被调用一次,我们可以通过调用模拟对象的 Verify() 方法来验证这一点。

//在模拟对象上的预期检验 person.Verify();

这是一个简略的预期设置的方法列表:

Expect(string methodName, object[] args)

ExpectAndReturn(string methodName, object returnVal, object[] args)

ExpectAndThrow(string methodName, Exception exceptionVal, object[] args)

ExpectNoCall(string methodName)

现在设置好所有的基本条件,我们就可以简单的在对 Hello 类的测试中应用 NMock 了。

这就是我们的测试类:

[TestFixture] public class HelloTest : Assertion {     [Test]     public void TestExpect()     {         //模拟依赖         IMock person = new DynamicMock(typeof(IPerson));         //设置值         person.ExpectAndReturn("Name", "John");         Hello hello = new Hello((IPerson) person.MockInstance);         AssertEquals("Hello John", hello.Greet());         //检验 Name 属性是否只被调用了一次         person.Verify();     } }

.Net单元测试之NMock

时间: 2024-10-08 18:22:03

.Net单元测试之NMock的相关文章

单元测试之Stub和Mock

单元测试之Stub和Mock FROM:http://www.cnblogs.com/TankXiao/archive/2012/03/06/2366073.html 在做单元测试的时候,我们会发现我们要测试的方法会引用很多外部依赖的对象,比如:(发送邮件,网络通讯,记录Log, 文件系统 之类的). 而我们没法控制这些外部依赖的对象.  为了解决这个问题,我们需要用到Stub和Mock来模拟这些外部依赖的对象,从而控制它们 阅读目录 实例 设计测试用例 什么是外部依赖 Stub和Mock的相同

谈谈单元测试之(四):测试工具 TestNG

前言 上一篇文章<测试工具 JUnit 4>中提到了 JUnit 4,并对 JUnit 4 做了简单的讨论,这篇文章我们将要围绕另一款测试工具讨论 -- TestNG.其实,这篇文章应该写在<测试工具 JUnit 3>之后,和<测试工具 JUnit 4>之前,为什么这么说呢? 那是因为,TestNG 是在 JUnit 3 之后出来了,而 JUnit 4 是在 TestNG 推出之后,综合 JUnit 3 的优点,并且借鉴了 TestNG 的优势,才推出的.但是,考虑到,

谈谈单元测试之(三):测试工具 JUnit 4

前言 上一篇文章<测试工具 JUnit 3>简单的讨论了 JUnit 3 的使用以及内部的方法.这篇文章将会在 JUnit 3 的基础上,讨论一下 JUnit 4 的新特性.同时,与 JUnit 3 做一个简单的对比.那么,废话就不多说了,直接进入正题. 介绍 JUnit 4.x 是利用了 Java 5 的特性(Annotation)的优势,使得测试比起 3.x 版本更加的方便简单,JUnit 4.x 不是旧版本的简单升级,它是一个全新的框架,整个框架的包结构已经彻底改变,但 4.x 版本仍然

单元测试之测试方法

单元测试面临的困难 职责不明确 类或者方法的职责不明确,违反了SRP原则. 类/方法如果处理了本不该它处理的逻辑,会造成单元测试需要关心过多的外部关联类. 静态方法 静态方法使得调用者直接面对实际的服务类,难以通过其它方式替代其实现,也难以扩展. 直接访问对象实例 调用者直接实例化服务对象,从而使用服务对象提供的服务.同静态方法一样,调用者直接面对服务类. 标准库 标准库中有非常多的接口调用使得调用者难以被测试. 准备数据 编写测试用例需要外部准备大量的数据. 可行的解决方案 重构系统 对于职责

单元测试之NSNull 检测

Unit Testing: 单元测试 测试这个词很容易理解,那么什么是单元(Unit)呢?一个单元指的就是应用程序中可以测试的最小单元.一组源代码可以测试,一般要求有明确的输入与输出.因此一般来说源代码中明确的包含输入输出的每一个方法被认为一个测试的单元(一个case).注意,这里的输出并不局限于方法的返回值对输入参数的改变,也包括方法在执行过程中改变的任何数据. 单元测试在程序里面可以理解一个模块一个方法,在每个可能存在的模块都进行测试,确保每个模块都没有问题,从而提高整体程序的质量. 单元测

我的单元测试之总结

单元测试 版权声明:本文为博主原创文章,未经博主允许不得转载. 以下关于单元测试的总结,是基于目前工作的内容进行的汇总,包括了单元测试的定义,单元测试assertion语句,单元测试的框架以及实践中的注意事项等.其中[***]为解释说明.在此推荐几本有关单元测试的书籍供参考.<单元测试的艺术><单元测试之道junit(Java版)><单元测试之道Nunit(C#版)>. Overview 一个UT当中,包括了准备数据,释放资源,执行要验证的那段逻辑代码,以及结果的验证等

Visual Studio 单元测试之二---顺序单元测试

原文:Visual Studio 单元测试之二---顺序单元测试 此文是上一篇博文:Visual Studio 单元测试之一---普通单元测试的后续篇章.如果读者对Visual Studio的单元测试不熟悉的话,请先参看上一篇.http://blog.csdn.net/tjvictor/archive/2011/02/09/6175362.aspx 本文会自动略去上篇中提到过的相关概念.方法.本文的例子可以使用下面的链接下载: http://download.csdn.net/source/30

单元测试之Mock

为什么需要Mock. 真实对象具有不确定的行为.所以会产生不可预测的结果. 真实对象很难被创建. 真实对象的某些行为很难被触发(如网络错误). 真实对象令程序的运行速度很慢. 真实对象有(或者是)用户界面. 测试需要询问真实对象它是如何被调用的. 真实对象实际上并不存在.例如其它小组开发的模块. 使用Mock的3个步骤 使用一个接口来描述该对象. 为产品代码实现该接口. 以测试为目的,在Mock对象中实现该接口. Test Double Dummy.被传递但是从不被实际使用的对象.通常用于填充参

玩转单元测试之Testing Spring MVC Controllers

玩转单元测试之 Testing Spring MVC Controllers 转载注明出处:http://www.cnblogs.com/wade-xu/p/4311657.html The Spring MVC Test framework provides first class JUnit support for testing client and server-side Spring MVC code through a fluent API. Typically it loads t