高瀬博道の技術ブログ

高瀬博道の技術ブログです。

もう2023年になったので、今さらNestJSに入門しようと思う - その21

前回

takasehiromichiex.com

カスタムプロバイダを使用するケース

カスタムプロバイダを使用するケースは、以下のようなものがあります。

  • Nestでクラスをインスタンス化する代わりにカスタムインスタンスを返す
  • 2番目の依存関係で既存のクラスを再利用する
  • テスト用にクラスをモックバージョンでオーバーライドする

様々なカスタムプロバイダを見てみましょう。

バリュープロバイダ

まずモックを作成します。

src/cats/cats.mock.service.ts
import { Cat } from "./cats.interface";

export const mockCatsService = {
  create(cat: Cat) {
    console.log("created.");
  },
  findAll(): Cat[] {
    return [
      {
        name: "test",
        age: 12,
        breed: "bang",
      },
    ];
  },
};

その後、モジュールに紐づけます。

src/cats/cats.module.ts
import { Module } from "@nestjs/common";
import { CatsController } from "./cats.controller";
import { mockCatsService } from "./cats.mock.service";
import { CatsService } from "./cats.service";

@Module({
  controllers: [CatsController],
  providers: [
    {
      provide: CatsService,
      useValue: mockCatsService,
    },
  ],
})
export class CatsModule {}

useValueによって、mockCatsServiceがモジュールに紐づけられました。

コントローラから参照されるのは、CatsServiceではなく、mockCatsServiceになります。

クラスプロバイダ

環境に応じて、トークンが解決されるクラスを動的に決定することができます。

dev向けとprod向けのサービスを作成します。

src/cats/cats.service.dev.ts
import { Injectable } from "@nestjs/common";
import { Cat } from "./cats.interface";

@Injectable()
export class CatsDevService {
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
    console.log("dev");
    this.cats.push(cat);
  }
  findAll(): Cat[] {
    console.log("dev");
    return this.cats;
  }
}
src/cats/cats.service.prod.ts
import { Injectable } from "@nestjs/common";
import { Cat } from "./cats.interface";

@Injectable()
export class CatsProdService {
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
    console.log("prod");
    this.cats.push(cat);
  }
  findAll(): Cat[] {
    console.log("prod");
    return this.cats;
  }
}

モジュールで分岐させます。

src/cats/cats.module.ts
import { Module } from "@nestjs/common";
import { env } from "process";
import { CatsController } from "./cats.controller";
import { CatsService } from "./cats.service";
import { CatsDevService } from "./cats.service.dev";
import { CatsProdService } from "./cats.service.prod";

@Module({
  controllers: [CatsController],
  providers: [
    {
      provide: CatsService,
      useClass:
        env.NODE_ENV === "development" ? CatsDevService : CatsProdService,
    },
  ],
})
export class CatsModule {}

useClassで分岐しました。

まとめ

ここまでで、

  • カスタムプロバイダを使用するケースについて
  • クラスプロバイダについて

を学びました。

大体入門できた気がするので、入門シリーズは終わろうと思います。

またテーマを分けてNestJSを深掘りしていきます。

コード

今回のコードは以下に格納しました。

github.com