Lilypie Primer PicLilypie Primer Ticker

martes, 18 de marzo de 2008

Incluir los métodos privados en las pruebas unitarias

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.


 


4 comentarios:

Anónimo dijo...

Hola, mira se que esto no va aqui, pero estoy un poco desesperado.
Te cuento:
Tengo una aplicacion que lee de ficheros(barcos), lo guarda en un arrayList y luego lo muestra mediante formularios(c#). Lo que quiero es que en un comboBOX me salga lo que guardado en el ArrayList, en concreto el nombre. Pruebo con un metodo get_nombre(hexo por mi) y nanai. Ayudame porfa. mi correo es ivan_10_as@hotmail.com

J. Marcos Troncoso dijo...

Hola Ivan,

Primero, te acosejaria usar una coleccion generica (como List<Barco> o BindingList<Barco>) en lugar de un ArrayList.

Segundo no me queda claro cual es el problema q tienes. Si es que no logras hacer el binding entre tus datos y el combo, o si tienes el binding funcionando y no logras que aparezca el nombre en el combo.


Para que aparezca el nombre necesitas implementar el método ToString() de tu clase y que te devueva el valor de la propiedad nombre.

Lamentablemente es toda la ayuda que te puedo dar con la información que proporcionas.. si me das mas detalles intentaré ayudarte de manera mas efectiva.

saludos

Pedro O. dijo...

Saludos.. Cuando comenzaste el artúclo decías: "métodos privados usando Reflection."..¿Qué es eso de reflection?.

Gracias

dahliawagley dijo...

Top Ten Casinos in Philadelphia | MapyRO
Discover the best 청주 출장안마 casinos in Philadelphia in real-time. 제천 출장샵 The best gambling sites in the city, with up-to-date information on the 계룡 출장마사지 best casinos 양산 출장샵 and 통영 출장샵