Estoy trabajando en un proyecto donde las llamadas internas de clase son habituales, pero los resultados son muchas veces valores simples. Ejemplo ( código no real ):
public boolean findError(Set<Thing1> set1, Set<Thing2> set2) {
if (!checkFirstCondition(set1, set2)) {
return false;
}
if (!checkSecondCondition(set1, set2)) {
return false;
}
return true;
}
Escribir pruebas unitarias para este tipo de código es realmente difícil, ya que solo quiero probar el sistema de condiciones y no la implementación de las condiciones reales. (Lo hago en pruebas separadas). De hecho, sería mejor si aprobara las funciones que implementan las condiciones y en las pruebas simplemente proporciono alguna simulación. El problema con este enfoque es el ruido: utilizamos mucho los genéricos .
Una solución de trabajo; sin embargo, es hacer que el objeto probado sea un espía y simular las llamadas a las funciones internas.
systemUnderTest = Mockito.spy(systemUnderTest);
doReturn(true).when(systemUnderTest).checkFirstCondition(....);
La preocupación aquí es que la implementación del SUT se cambia efectivamente y puede ser problemático mantener las pruebas sincronizadas con la implementación. ¿Es esto cierto? ¿Existe la mejor práctica para evitar este caos de las llamadas a métodos internos?
Tenga en cuenta que estamos hablando de partes de un algoritmo, por lo que dividirlo en varias clases puede no ser una decisión deseada.
fuente
Si ambos
findError()
ycheckFirstCondition()
etc. son métodos públicos de su clase, entoncesfindError()
es efectivamente una fachada para la funcionalidad que ya está disponible desde la misma API. No hay nada de malo en eso, pero significa que tiene que escribir pruebas que sean muy similares a las pruebas ya existentes. Esta duplicación simplemente refleja la duplicación en su interfaz pública. Esa no es razón para tratar este método de manera diferente a los demás.fuente
Las pruebas unitarias deben probar el contrato; Es lo único importante para ellos. Probar cualquier cosa que no sea parte del contrato no es solo una pérdida de tiempo, es una posible fuente de error. Cada vez que ve a un desarrollador que cambia las pruebas cuando cambia un detalle de implementación, deben sonar las alarmas; ese desarrollador puede estar (intencionalmente o no) ocultando sus errores. Probar deliberadamente los detalles de implementación obliga a este mal hábito, lo que hace más probable que los errores se enmascaren.
Las llamadas internas son un detalle de implementación y solo deberían ser de interés para medir el rendimiento . Que no suele ser el trabajo de las pruebas unitarias.
fuente
a
contiene una llamada al métodob
en la misma clase, las pruebas dea
deben incluir pruebas deb
. Y no hay forma de cambiar esto, siempre y cuandob
no se pasea
como parámetro. Pero veo que no hay otra solución.b
es parte de la interfaz pública, debe probarse de todos modos. Si no es así, no necesita ser probado. Si lo hiciste público solo porque querías probarlo, lo hiciste mal.En primer lugar, me pregunto qué es difícil de probar sobre la función de ejemplo que escribió. Hasta donde puedo ver, simplemente puede pasar varias entradas y verificar para asegurarse de que se devuelve el valor booleano correcto. ¿Qué me estoy perdiendo?
En cuanto a los espías, el tipo de prueba llamada "caja blanca" que utiliza espías y simulacros es órdenes de magnitud más trabajo para escribir, no solo porque hay mucho más código de prueba para escribir, sino cada vez que la implementación es cambiado, también debe cambiar las pruebas (incluso si la interfaz sigue siendo la misma). Y este tipo de pruebas también es menos confiable que las pruebas de recuadro negro, porque debe asegurarse de que todo ese código de prueba adicional sea correcto, y aunque puede confiar en que las pruebas unitarias de recuadro negro fallarán si no coinciden con la interfaz , no puede confiar en eso sobre el uso excesivo de códigos simulacros porque a veces la prueba ni siquiera prueba mucho código real, solo simulacros. Si los simulacros son incorrectos, lo más probable es que sus pruebas tengan éxito, pero su código aún está roto.
Cualquier persona que tenga experiencia con las pruebas de caja blanca puede decirle que es un fastidio escribir y mantener. Junto con el hecho de que son menos confiables, las pruebas de caja blanca son simplemente muy inferiores en la mayoría de los casos.
fuente