Ya, me cansé que me digan que no pueden testear un método porque es privado, que no tiene sentido cambiarlo a público solo para testearlo así que no hay test unitario para el método, se puede testear un método privado en c# sin cambiar su acceso.
Ejemplo en C# para los escépticos, supongamos una clase matemática que suma los números desde x a y, en un método privado, con eso tenemos la siguiente clase.
public class Matematica { private int SumaNumeros(int x, int y) { int acumulador = 0; for (int i = x; i <= y; i++) { acumulador += i; } return acumulador; } }
Ahora para testearlo, en una clase de test de visual studio, utilizamos el la clase PrivateObject con la cual envolvemos el objeto a testear y usando el método Invoke podemos llamar al método privado con la lista de parámetros de entrada que este toma listados para el lado, este método retorna un objeto, que es donde se envuelve la respuesta de este método.
El ejemplo en código de como hacer estos llamados.
[TestMethod] public void ProbandoSumadorPrivado() { var objetoTest = new Matematica(); var privateTest = new PrivateObject(objetoTest); object obj = privateTest.Invoke("SumaNumeros", 1, 4); Assert.AreEqual(10, (int) obj); }
Como se ve, se crea el objeto matemática y se hace un nuevo PrivateObject con el objeto matemática como parámetro del constructor, para este nuevo objeto se llama al método Invoke, se pasa el nombre del método que se quiere probar como string como primer argumento y los parámetros listados hacia el lado, como los argumentos siguientes del método Invoke, como respuesta esté entrega un objeto del tipo object, la repuesta queda en la variable obj, y para poder ser comparada se debe convertir en el tipo de dato que retorna el método en este caso un entero.
Esto no rompe el principio Open-Close de orientación a objetos, porque como es un método de test, este debe conocer que es lo que entrega y de antemano la respuesta al test para poder ser un test efectivo.
Así que ya sabe, nunca mas diga «no puedo testear métodos privados en C#».
septiembre 11, 2013 at 11:32 am
Buen post!
Creo que más que si se puede o no testear métodos privados, me haría la pregunta si es necesario hacerlo.
No soy de la idea de testear métodos privados, pues son detalles de implementación. En mi experiencia, los test que creas de ésta forma terminan acoplados al código que prueban y por tanto demasiado frágiles, pues vas a tener que tocarlos cada vez que refactorices.
Es mas sano testear comportamiento, y este se expone en un objeto a traves de sus métodos públicos.
Saludos!
septiembre 11, 2013 at 11:43 am
La verdad es que te encuentro razón, no es para andar testeando todos los métodos privados que uno tiene, porque como dices pueden ser parte de un comportamiento y ser solo un detalle de implementación, pero es bueno tener la opción, sobretodo si estas haciendo funcionar algo, en lugar de levantar la app completa solo corres el test y lo puedes debugear, me pasó a mi intentando conectarme a un ftp me salía un error y en lugar de abrir y levantar una y otra vez la aplicación cree un test unitario que era mucho más eficiente, y como era un método privado usé el PrivateObject.
Pero hago mea culpa, testear comportamiento y no implementación, anotado… nunca más… aunque igual es bueno tener la opción XD.