Introducing TDD into a decade-old monolith that lacked unit tests felt impossible: 200 k lines of Java code, no dependency injection, and a database schema that changed under our feet. Here’s how we rolled it out without halting feature delivery.
Step 1 – Identify Seams
Using Michael Feathers’ “seam” model, we wrapped external DB calls behind interfaces and used Mockito + H2 for in-memory testing.
Step 2 – Golden Master Tests
// Capture current behaviour before refactor
@Test
void shouldPreserveLegacyCalculation() {
String output = legacyService.calculateCharges(input);
Approvals.verify(output);
}
Step 3 – Incremental Adoption
- Every new class is TDD-first
- Refactor only modules currently under active feature work
- Code coverage gate raised from 0 % to 60 % within 6 months
Within a quarter we cut production defects in touched modules by 40 % and reduced mean-time-to-repair from days to hours.
← Back to all articles