4. 测试私有方法 测试私有方法稍微复杂些,但我们可以利用System.Reflection。你可以利用反射动态的访问一个类型的方法,包括实例和静态的私有方法。要注意的是访问私有方法需要ReflectionPermission,但在开发机或BUILD机上运行单元测试不是问题。 假设我们要测试ClassLibrary1.MyObject类的MyPrivateMethod私有方法: private string MyPrivateMethod(string strInput, DateTime dt, double dbl) { return this.Name + ": " + strInput + ", " + dt.ToString() + ", " + dbl.ToString(); } 一种解决方法是建立一个UnitTestUtilities 工程包含一个UnitTestUtilities.Helper类,用于通过反射调用测试方法。 public static object RunStaticMethod(System.Type t, string strMethod, object [] aobjParams) { BindingFlags eFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; return RunMethod(t, strMethod, null, aobjParams, eFlags); } //end of method public static object RunInstanceMethod(System.Type t, string strMethod, object objInstance, object [] aobjParams) { BindingFlags eFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; return RunMethod(t, strMethod, objInstance, aobjParams, eFlags); } //end of method private static object RunMethod(System.Type t, string strMethod, object objInstance, object [] aobjParams, BindingFlags eFlags) { MethodInfo m; try { m = t.GetMethod(strMethod, eFlags); if (m == null) { throw new ArgumentException("There is no method '" + strMethod + "' for type '" + t.ToString() + "'."); } object objRet = m.Invoke(objInstance, aobjParams); return objRet; } catch { throw; } } //end of method 私有方法RunMethod利用反射时必须的参数,调用相关的被测试方法并返回值。这里有两个封装的方法RunStaticMethod和RunInstanceMethod,分别针对静太方法和实例方法。 大概看一下这两个方法的代码,首先取得类型的MethodInfo,因为我们调用的是已经存在的方法,如果是空方法,则产生一个异常。一旦有了MethodInfo,我们就可以调用实例(如果是static,则为null)的私有方法,并传入参数数组。 我们可以在NUnit中这样使用: [Test] public void TestPrivateInstanceMethod() { string strExpected = "MyName: Hello, 5/24/2004 12:00:00 AM, 2.1"; ClassLibrary1.MyObject objInstance = new MyObject("MyName"); object obj = UnitTestUtilities.Helper.RunInstanceMethod( typeof(ClassLibrary1.MyObject), "MyPrivateMethod", objInstance, new object[3] {"Hello", new DateTime(2004,05,24), 2.1}); string strActual = Convert.ToString(obj); Assert.AreEqual(strExpected,strActual); } 标准 满足性 透明性 唯一的额外代码- UnitTestUtilities,不会包含在产品中一起发布。 范围 该方法中没有任何东西是仅依赖于调试模式。 简单性 该方法可以在一个单独调用中调用任何方法。利用UnitTestUtilities的唯一问题就是为RunInstanceMethod或RunStaticMethod创建正确的参数(方法名、数据类型等)。因为方法是动态调用的,参数在编译时不会被检查。 5. 结论 虽然对私有方法的测试存在争论,至少我们现在知道如何进行测试了。我们可以通过包装基类建立一个派生类TesterClass用于测试其protected方法,通过UnitTestUtility帮助类利用反射可以测试类中的私有方法。所有这些技术都可利于提高测试覆盖率。 参考: http://www.codeproject.com/csharp/TestNonPublicMembers.asp

评论