Aunque existe un gran debate acerca de si se debe incluir o no los métodos privados en las pruebas unitarias, siempre es bueno disponer de alguna forma de hacerlo.
En este post les mostraré una sencilla forma de invocar métodos privados usando Reflection.
Implementaremos la clase PrivateMethodCaller asi:
public class PrivateMethodCaller
{
public static object Invoke(Type t, string methodName, object[] parameters)
{
MethodInfo mi = t.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic);
return InvokeMethod(mi, null, parameters);
}
public static object Invoke(object instance, string methodName, object[] parameters)
{
MethodInfo mi = instance.GetType().GetMethod(methodName, BindingFlags.NonPublic|BindingFlags.Instance);
return InvokeMethod(mi, instance, parameters);
}
private static object InvokeMethod(MethodInfo mi, object instance, object[] parameters)
{
if (mi == null)
{
throw new InvalidOperationException("No se pudo encontrar el método");
}
return mi.Invoke(instance, parameters);
}
}
Nuestra clase contiene un solo método: Invoke que toma dos formas:
La primera acepta un parámetro tipo Type. Esta versión del método nos permite invocar métodos estáticos.
La segunda acepta un parámetro tipo object. Esta versión nos permite invocar métodos no estáticos.
Veamos ahora como usamos esta clase desde nuestras pruebas unitarias.
Crearemos una clase muy simple que nos servirá como ejemplo:
public class ClassUnderTest
{
private static int StaticMethod(int a, int b)
{
return a + b;
}
private int InstanceMethod(int a, int b)
{
return a + b;
}
}
Hemos definido dos métodos en nuestra clase de prueba. Uno estático y el otro de instancia.
Ahora veamos como implementamos nuestras pruebas unitarias usando NUnit:
[TestFixture]
public class PrivateMethodTests
{
[Test]
public void StaticMethodTest()
{
int res = (int)PrivateMethodCaller.Invoke(typeof(ClassUnderTest), "StaticMethod", new object[] { 1, 2 });
Assert.AreEqual(3, res);
}
[Test]
public void InstanceMethodTest()
{
int res = (int)PrivateMethodCaller.Invoke(new ClassUnderTest(), "InstanceMethod", new object[] { 4,5});
Assert.AreEqual(9, res);
}
}
Como podemos ver ya somos capaces de invocar los métodos privados y testear sus resultados.
Espero que esta información les sea de utilidad.
Saludos.