actualización: Ver this question too.
sólo puedo responder a algunas partes aquí:
está bien para romper todas las dependencias que utilizan las interfaces sólo para hacer una clase comprobable? Implica una sobrecarga significativa en el tiempo de ejecución debido a muchas llamadas virtuales en lugar de invocaciones de métodos simples.
Si su rendimiento sufrirá demasiado debido a ello, no (punto de referencia!). Si su desarrollo sufre demasiado, no (estimar el esfuerzo extra). Si parece que no va a importar mucho y ayuda a la larga y te ayuda con la calidad, sí.
Siempre podría 'amigo' sus clases de prueba, o un objeto TestAccessor a través del cual sus pruebas podrían investigar cosas dentro de él. Eso evita hacer todo dinámicamente despachable solo para probar. (suena como un buen trabajo).
El diseño de interfaces comprobables no es fácil. A veces debes agregar algunos métodos adicionales que acceden a las entrañas solo para probar. Te hace temblar un poco, pero es bueno tenerlo y la mayoría de las veces esas funciones también son útiles en la aplicación real, tarde o temprano.
Si realizo una refactorización, ocurre con mucha frecuencia que tengo que volver a escribir completamente la prueba unitaria debido a cambios masivos en la lógica. Mi código cambia muy a menudo y cambia la lógica fundamental del procesamiento de datos. No veo una manera de escribir pruebas unitarias que no tengan que cambiar en una refactorización grande.
Las grandes refactorizaciones por definición cambian mucho, incluidas las pruebas. Se feliz de tenerlos, ya que probarán cosas después de refaccionar también.
Si dedica más tiempo a refactorizar que a crear nuevas funciones, tal vez debería pensar un poco más antes de codificar para encontrar mejores interfaces que puedan soportar más cambios. Además, escribir pruebas unitarias antes de que las interfaces sean estables es un problema, no importa lo que hagas.
Cuantos más códigos tenga contra una interfaz que cambia mucho, más código tendrá que cambiar cada vez. Creo que tu problema yace allí. Logré tener interfaces suficientemente estables en la mayoría de los lugares, y refactorizar solo partes de vez en cuando.
Espero que ayude.
No es que no piense antes de codificar. Muy a menudo los requisitos cambian después de que el cliente haya visto la implementación inicial de una nueva característica. Otra razón es que a veces es necesario realizar una implementación rápida y sucia por motivos de marketing. En este caso, no me molesto con las pruebas unitarias, pero a veces el truco rápido y sucio se convierte en algo real debido a una estrecha programación. No es fácil hacer que este desastre sea comprobable más adelante. – frast
Lo siento, no quise dar a entender exactamente eso. ;) Sé que la vida real es difícil de trabajar a veces. Quick'n dirty hacks viene con una deuda, ya sea prueba faltante, refactorización/limpieza necesaria o ambos. O bien paga en efectivo primero (trabajo adecuado) o paga con el alquiler después (limpieza). Sin moverse de eso. Es difícil trabajar en condiciones en las que no se puede influir en eso. (Estado allí ...) – Macke