使用InternalsVisibleTo属性
一个会影响到单元测试编写的难题是给测试项目增加合适的引用,以访问我们想要测试的方法。单元测试的要点是检测代码并确保代码正常运行。然而,在一个设计良好的类中,许多方法应该是类私有的,它们是不能被外部代码访问的。这也带来了一个问题,因为这限制了我们的测试访问方法的能力。
一种解决方案是把我们测试的方法都设置为公有的,但是当内部方法没有正确使用时,这种解决方案会导致在后期引发问题。假如一个新的开发人员加盟进来,他并不知道某个方法只是为了测试才设置为公有的。他可能会认为所有公有的方法都是可用的,然后就使用了这个方法,而这很有可能会为代码引入很严重的缺陷。
另一种解决方案是把同一项目的测试类作为动态代码。如果我们这么做而且将方法设置为内部的,那就可以解决问题;然而,现在测试代码作为动态代码编译到同一个DLL中去,会导致文件很臃肿。
.NET框架用InternalsVisibleTo项目属性来处理这个问题。通过在AssemblyInfo.cs文件中增加InternalsVisibleTo属性,我们可以把一个内部的属性或方法只暴露给解决方案中的指定工程。这确保测试类只访问那些需要的方法,同时保持对业务逻辑的合理封装。
图3.10展示了在哪里可以找到AssemblyInfo.cs文件。
代码清单3.10展示了InternalsVisibleTo属性究竟是什么样的。代码清单3.10的最后一行就是一个示例。
代码清单3.10 InternalsVisibleTo的一个示例
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- // General Information about an assembly is controlled through the following
- // set of attributes. Change these attribute values to modify the information
- // associated with an assembly.
- [assembly: AssemblyTitle("CodeSamples")]
- [assembly: AssemblyDescription("")]
- [assembly: AssemblyConfiguration("")]
- [assembly: AssemblyCompany("Reengineering .NET")]
- [assembly: AssemblyProduct("CodeSamples")]
- [assembly: AssemblyCopyright("Copyright ? Brad Irby")]
- [assembly: AssemblyTrademark("")]
- [assembly: AssemblyCulture("")]
- // Setting ComVisible to false makes the types in this assembly not visible
- // to COM components. If you need to access a type in this assembly from
- // COM, set the ComVisible attribute to true on that type.
- [assembly: ComVisible(false)]
- // The following GUID is for the ID of the typelib if
- // this project is exposed to COM.
- [assembly: Guid("693b33bf-7738-42b0-b743-ed05a8d28d8e")]
- // Version information for an assembly consists of the following four values:
- //
- // Major Version
- // Minor Version
- // Build Number
- // Revision
- //
- // You can specify all the values or you can default the
- // Build and Revision Numbers
- // by using the '*' as shown below:
- // [assembly: AssemblyVersion("1.0.*")]
- [assembly: AssemblyVersion("1.0.0.0")]
- [assembly: AssemblyFileVersion("1.0.0.0")]
- [assembly: InternalsVisibleTo("CodeSampleUnitTests")]
该字符串(CodeSampleUnitTests)是授权使用内部方法的工程(即测试工程)名称。这行应该添加到含有测试逻辑的动态代码工程的AssemblyInfo.cs文件中。代码清单3.11展示了私有方法的一个示例,这个方法被标记为Internal以便可以由测试访问。
代码清单3.11 内部方法示例
- namespace CodeSamples.Ch03_UnitTesting.Listing11
- {
- public class SampleInternalMethod
- {
- /// <summary>
- /// Sample method with the internal setting
- /// </summary>
- internal void InternalMethod(string pMessage)
- {
- //code goes here
- }
- }
- }