标签:
Microsoft Fakes 通过将应用程序的其余部分替换为存根 或填充码 来帮助隔离正在测试的代码。 这些是受你的测试控制的小段代码。 通过隔离接受测试的代码,你将会知道,如果测试失败,原因就在这里而不是其他地方。 即使应用程序的其他部分不起作用,存根和填充码也能让你测试代码。
Fakes 有两种风格:
要求
通常,你将 Visual Studio 项目视为一个组件,这是因为你同时开发和更新这些类。 对于该项目对你的解决方案中的其他项目所作的调用或对该项目引用的其他程序集所作的调用,应考虑使用存根和填充码。
一般原则是,为在 Visual Studio 解决方案中进行的调用使用存根,并为对其他引用的程序集的调用使用填充码。 这是因为在你自己的解决方案中,通过按照存根要求的方式定义接口来分离组件是一个很好的做法。 但是,外部程序集(如 System.dll)通常没有单独的接口定义,因此你必须改用填充码。
其他需要注意的事项还有:
性能。填充码运行较慢,因为它们在运行时会重新编写你的代码。 存根没有这项性能开销,与虚方法运行的速度一样快。
静态方法,密封类型。你只能使用存根实现接口。 因此,存根类型不能用于静态方法、非虚方法、密封虚方法、密封类型中的方法,等等。
内部类型。存根和填充码都可用于可通过程序集特性 InternalsVisibleToAttribute 访问的内部类型。
私有方法。如果方法签名中的所有类型都是可见的,则填充码可替换对私有方法的调用。 存根只能替换可见方法。
接口和抽象方法。存根提供了可用于测试的接口和抽象方法的实现。 填充码无法检测接口和抽象方法,因为它们没有方法体。
通常,我们建议使用存根类型来与基本代码中的依赖项隔离。 可以通过隐藏接口后面的组件执行此操作。 填充码类型可用于与不提供可测试的 API 的第三方组件隔离。
(有关更多详细说明,请参见使用存根针对单元测试隔离应用程序的各个部分。)
若要使用存根,你在编写要测试的代码时不应明确提及应用程序的其他组件中的类。 "组件"是指一个类或一起开发和更新的多个类,通常包含在一个 Visual Studio 项目中。 应使用接口来声明变量和参数,并且应使用工厂来传入或创建其他组件的实例。 例如,如果 StockFeed 是应用程序的另一个组件中的类,则可以认为以下内容是错误的:
1 return (new StockFeed()).GetSharePrice("COOO"); // Bad
相反,应该定义可由另一个组件实现的接口以及可由存根出于测试目实现的接口:
1 public int GetContosoPrice(IStockFeed feed) 2 { 3 return feed.GetSharePrice("COOO"); 4 }
1 [TestClass] 2 class TestStockAnalyzer 3 { 4 [TestMethod] 5 public void TestContosoStockPrice() 6 { 7 // Arrange: 8 // Create the fake stockFeed: 9 IStockFeed stockFeed = 10 new StockAnalysis.Fakes.StubIStockFeed() // Generated by Fakes. 11 { 12 // Define each method: 13 // Name is original name + parameter types: 14 GetSharePriceString = (company) => { return 1234; } 15 }; 16 // In the completed application, stockFeed would be a real one: 17 var componentUnderTest = new StockAnalyzer(stockFeed); 18 // Act: 19 int actualValue = componentUnderTest.GetContosoPrice(); 20 // Assert: 21 Assert.AreEqual(1234, actualValue); 22 } 23 ...
此处最为神奇的就是类 StubIStockFeed。 对于所引用程序集中的每个接口,Microsoft Fakes 机制将生成一个存根类。 存根类的名称派生自接口的名称,前缀为"Fakes.Stub",并且在名称后面追加了参数类型名称。
另外,还会为属性的 getter 和 setter、事件和泛型方法生成存根。 有关详细信息,请参阅使用存根针对单元测试隔离应用程序的各个部分。
(有关更多详细说明,请参见使用填充码针对单元测试将应用程序与程序集隔离。)
假定你的组件包含对 DateTime.Now 的调用:
1 // Code under test: 2 public int GetTheCurrentYear() 3 { 4 return DateTime.Now.Year; 5 }
在测试过程中,你希望填充 Now 属性,因为每次调用时实际版本都会返回不同的值,从而造成了不便。
若要使用填充码,你不必修改应用程序代码或以特定方式来编写代码。
在"解决方案资源管理器"中,打开单元测试项目的引用,然后选择对包含要虚设的方法的程序集的引用。 在此示例中,DateTime 类在 System.dll 中。 若要查看 Visual Basic 项目中的引用,请选择"显示所有文件"。
选择"添加 Fakes 程序集"。
1 [TestClass] 2 public class TestClass1 3 { 4 [TestMethod] 5 public void TestCurrentYear() 6 { 7 int fixedYear = 2000; 8 // Shims can be used only in a ShimsContext: 9 using (ShimsContext.Create()) 10 { 11 // Arrange: 12 // Shim DateTime.Now to return a fixed date: 13 System.Fakes.ShimDateTime.NowGet =() => 15 { return new DateTime(fixedYear, 1, 1); }; 16 // Instantiate the component under test: 17 var componentUnderTest = new MyComponent(); 18 // Act: 19 int year = componentUnderTest.GetTheCurrentYear(); 20 // Assert: 21 // This will always be true if the component is working: 22 ssert.AreEqual(fixedYear, year); 23 } 24 } 25 } 26 27
填充码类名称是通过在原始类型名称前加上 Fakes.Shim 前缀构成的。 在方法名称后面将会追加参数名称。 (您不需要添加对 System.Fakes 的任何项目引用)
前面的示例对一个静态方法使用了填充码。 若要将填充码用于实例方法,请在类型名称和方法名称之间写入 AllInstances:
System.IO.Fakes.ShimFile.AllInstances.ReadToEnd = ...
您不必引用关于 System.IO.Fakes 的任何内容: 它由填充程序的生成过程创建。
你还可以为特定实例、构造函数和属性创建填充码。 有关详细信息,请参阅使用填充码针对单元测试将应用程序与程序集隔离。
Microsoft Fakes 中的代码生成、编译和命名约定
标签:
原文地址:http://www.cnblogs.com/BMFramework/p/4522835.html