Dependency Injection and Testability
#Services should depend on abstractions or injectable collaborators where practical.
For example, an order service can receive a payment gateway interface rather than directly importing a concrete Stripe or payment implementation.
Tests can then provide a fake implementation and test business behavior deterministically.
Dependency injection is not required for every small application, but explicit dependencies improve testability and architecture as complexity increases.
Service with Dependency Injection
class OrderService {
constructor(orderRepository, paymentGateway) {
this.orderRepository = orderRepository;
this.paymentGateway = paymentGateway;
}
async pay(orderId) {
const order = await this.orderRepository.findById(orderId);
return this.paymentGateway.charge(order.total);
}
}💡 The service depends on collaborators supplied externally, making business logic easier to test.