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,
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
评论