Skip to main content

Dependency Injection

Dependency injection supplies a component's dependencies from outside rather than having it create them, improving decoupling and testability.

Dependency injection (DI) is a technique for supplying a component with the things it depends on from the outside, instead of having the component construct or locate them itself. It is a concrete way to apply the broader principle of inversion of control: a component declares what it needs, and something else provides it.

How It Works

Without DI, a class might create its own database connection or HTTP client inside its constructor, hard-wiring itself to specific implementations. With DI, those dependencies are passed in — typically through the constructor, a method parameter, or a property. The most common form is constructor injection, where collaborators are provided when the object is created. Many frameworks (Spring, .NET, Angular, NestJS) include a DI container that automatically constructs and wires up the object graph, but DI is a pattern, not a framework, and can be done by hand.

Why It Matters

By depending on abstractions supplied from outside, components become loosely coupled and easy to recombine. The biggest practical payoff is testability: in a unit test you can inject a mock or stub in place of a real database or service, isolating the code under test. DI also makes it easy to swap implementations — a real payment gateway in production, a fake one in development — and centralizes how the application's components are assembled.

The trade-offs are added indirection and, with heavy container use, configuration complexity that can obscure how objects are created.

Related Terms

Unit tests and mocking rely on DI to substitute dependencies. Integration tests may inject real collaborators. DI helps keep core logic close to pure functions by isolating impure dependencies.