Hola, cuando se parte de código legado siempre es dificil aplicar TDD ya que suele haber código muy acoplado y no están bien definidas las responsabilidades de cada clase o método. Lo ideal es que el principio de resonsabilidad única impere en ese código, pero no siempre es así, de ahí que existan dificultades para crear tests unitarios.
TDD debería ser lo último si estas en esta situación, así que yo empezaría refactorizando, por ejemplo extrayendo métodos o clases, y aplicando tests unitarios a esa refactorización. Incluso puedes empezar aplicando TDD en esa refactorización si puedes crear el test antes que la extracción de código. Eso sería un inicio. Puedes hacer TDD para extraer una responsabilidad de otro método creando uno nuevo y adpatar el código extraido para satisfacer ese test.
También puedes, si añades nuevo código, crearlo en un método independiente y llamarlo desde el que incluye toda la lógica. Aquí haría TDD con ese método nuevo aunque dejases sin testear el método con múltiples responsabilidades. Esta es una forma rápida de empezar sin meterte a hacer grandes refactorizaciones.
Si hay llamadas a base de datos u otros servicios hay que desacoplar y pasar objetos falsos que emulen ese comportamiento; volvemos a lo mismo, antes hay que refactorizar apoyandose en tests y hacer inyección de dependencias para poder pasar los objetos falsos.
Si un test llama a una base de datos o a terceros no es un test unitario, es otro tipo de test que puedes crear (yo los hago), pero no son test unitarios y no son validos para hacer TDD.
Así que si tienes código muy acoplado y complejo:
- Empieza refactorizando para desacoplar el código.
- Crear los test unitarios que puedas aunque sea tras refactorizar (El test despues de extraer código).
- Hacer TDD pensando en esa refactorización si es posible (El test antes que el código que vas a modificar).
Saludos.