NestJS

Lesson 02

Dependency injection providers

Use NestJS providers and injection tokens so services declare their collaborators instead of constructing infrastructure directly.

Good Code

reviews.service.ts
import { Inject, Injectable } from "@nestjs/common";

export const REVIEWS_REPOSITORY = Symbol("REVIEWS_REPOSITORY");

@Injectable()
export class ReviewsService {
  constructor(
    @Inject(REVIEWS_REPOSITORY)
    private readonly reviews: ReviewsRepository,
  ) {}

  // The service declares the repository it needs.
  findPending() {
    return this.reviews.findByStatus("pending");
  }
}

Bad Code

reviews.service.ts
import { Injectable } from "@nestjs/common";
import { MongoClient } from "mongodb";

@Injectable()
export class ReviewsService {
  async findPending() {
    // Direct construction hides connection and test boundaries.
    const client = new MongoClient(process.env.MONGO_URL!);
    const reviews = client.db().collection("reviews");
    return reviews.find({ status: "pending" }).toArray();
  }
}

Review Notes

What to review

Good Code

The good version declares a repository dependency at the constructor boundary. Tests can provide a fake repository without opening a database connection.

Bad Code

The bad version creates a database client inside the method. Every call now depends on environment variables, network access, and driver setup.

Takeaways

  • Constructor injection makes dependencies visible and gives tests a stable place to replace infrastructure.