transform The Refactoring Process
warning TIGHT COUPLING
The "New" Operator is the Enemy
Your original code instantiates new Database() directly inside the method.
This creates a hard dependency. When you try to write a unit test, your code will try to connect to a real database. You cannot stop it, intercept it, or mock it.
// Original Code
class PersonController { public void save(Person person) { // PROBLEM: new Database().save(person); } }
// Step 1: Define Interface
// 1. Create an interface (Contract) interface IDatabase { void save(Person person); } class RealDatabase implements IDatabase { public void save(Person p) { ... } }
// Step 2: Constructor Injection
class PersonController { private final IDatabase database; // Inject dependency via constructor public PersonController(IDatabase db) { this.database = db; } public void save(Person person) { // Use the injected instance this.database.save(person); } }
// The Unit Test
class PersonControllerTest { @Test public void testSaveInIsolation() { // 1. Arrange: Create Mock MockDatabase mockDb = new MockDatabase(); PersonController ctrl = new PersonController(mockDb); Person p = new Person("John"); // 2. Act ctrl.save(p); // 3. Assert: Verify mock was called assertTrue(mockDb.wasSaveCalled); } }
science Interactive Test Simulator
Assemble your components and run the test to see Dependency Injection in action.
Class Under Test
settings
PersonController
Constructor needs: IDatabase
Select Dependency to Inject:
> Waiting for setup...
code Complete Refactored Class
public class PersonController { private final IDatabase database; // Constructor Injection public PersonController(IDatabase database) { this.database = database; } public void save(Person person) { this.database.save(person); } }
science Complete Unit Test
public class PersonControllerTest { public void testSave() { // 1. Mock MockDatabase mock = new MockDatabase(); // 2. Inject Mock PersonController ctrl = new PersonController(mock); // 3. Run & Verify ctrl.save(new Person("Alice")); assert(mock.savedPerson != null); } }