如何使用Microsoft Fakes 进行单元测试

发表于:2012-11-13来源:博客园作者:重典点击数: 标签:单元测试
如何使用Microsoft Fakes 进行单元测试. Microsoft Fakes 可以提供成员模拟的方法.以方便进行单元测试 如果不使用模拟方法我们要关心很多东西,如数据库的数据变化,接口调用导致的变化,文件、及其它资源的访问等问题。

  Microsoft Fakes 可以提供成员模拟的方法.以方便进行单元测试

  如果不使用模拟方法我们要关心很多东西,如数据库的数据变化,接口调用导致的变化,文件、及其它资源的访问等问题。

  使用模拟我们则可以只关系我们需要测试的那部分逻辑。

clip_image001

  一 、Stub 和 Shim

  Microsoft Fakes 提供了两种模拟类型成员的方式.以下两种方式的替代实现,都可以由委托来重新实现.

  1.Stub Type,存根类型,可以动态地为接口及非密封的virtual或属性附加委托,以重新定义其实现,生成的类为强类型.

  2.Shim Types,填充类型,解决了密封类或static成员的问题,T的填充类型ShimT可以为T的每个成员提供一个替代实现

  二 、选择原则

  由于Stub和Shim的实现方式不同,所以它们也有不同的要求,下面总结了选择它们的一些原则:

  性能方面:运行时使用Shim重写会影响性能,Stub由于使用的是虚方法,则无此问题

  对static方法/sealed类型:Stub类型只可以重写虚方法,因此,它不适用于static方法/sealed方法/sealed类中的方法,等

  Internal类型:对于标记了InternalsVisibleToAttribute的内部类型,Fakes也可以起作用

  private方法:如果private方法的签名上的所有类型都是可见类型,那么可以通过Shim来替换实现.Stub只能替换可见方法.

  接口和抽象方法:Stub可以提供接口或抽象方法的替代实现.Shim则不能,因为没有实际的方法体.

  所以建议在一般情况下使用Stub来支持那些可测试性做的非常好的类型,而用Shim来解决那些耦合很大,可测试性很差的代码或三方组件.

  三、如何使用Fakes

  假设我们在项目ClassLibrary1中有以下几个类

  1: public interface IDataAccess

  2: {

  3: int Read();

  4: }

  5:

  6: public class MyDataAccess : IDataAccess

  7: {

  8: public int Read()

  9: {

  10: return Tools.GetNum();

  11: }

  12: }

  13:

  14: public class Tools

  15: {

  16: static public int GetNum()

  17: {

  18: return 1;

  19: }

  20: }

  21:

  22: public class MyClass

  23: {

  24: public static int GetMyData(IDataAccess obj)

  25: {

  26: //其它逻辑

  27: return obj.Read();

  28: }

  29: }

  我们要使用Fakes进行测试只需要在测试项目中引用 ClassLibrary1,并且在之上右键->建立 Fakes即可使用Fakes

  之后我们就可以使用类似以下代码来模拟一个IDataAccess的实例 ,MyClass.GetMyData 这个static方法的实现

  前者即使用Stub,后者即Shim

  1: [TestClass]

  2: public class UnitTest1

  3: {

  4: [TestMethod]

  5: public void StubTest()

  6: {

  7: IDataAccess stockFeed = new ClassLibrary1.Fakes.StubIDataAccess()

  8: {

  9: Read = () => { return 2; }

  10: };

  11: Assert.AreEqual(2, MyClass.GetMyData(stockFeed));

  12:

  13: }

  14: [TestMethod]

  15: public void ShimTest()

  16: {

  17: using (ShimsContext.Create())

  18: {

  19: ClassLibrary1.Fakes.ShimMyClass.GetMyDataIDataAccess = (inc) => { return 2; };

  20: Assert.AreEqual(2, MyClass.GetMyData(null));

  21: }

  22:

  23: }

  24:

  25: }

  Stub 与其它Mock差不多,只是使用委托来改变方法实现

  而Shim则需要建立 ShimsContext的作用域

原文转自:http://www.ltesting.net