From 83a5bc0ecd05a352e164bda1f66f48962159c427 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 5 Mar 2024 14:26:16 +0900 Subject: [PATCH] =?UTF-8?q?=20doc:=20Nest=E3=81=A7=E5=BE=AA=E7=92=B0?= =?UTF-8?q?=E4=BE=9D=E5=AD=98=E3=81=8C=E3=81=82=E3=82=8B=E5=A0=B4=E5=90=88?= =?UTF-8?q?=E3=81=AECONTRIBUTING.md=E3=81=AB=E6=9B=B8=E3=81=8F=20=20(#1352?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * doc: Nestモジュールテストの例をCONTRIBUTING.mdに書く * rm normal test * forwardRef --- CONTRIBUTING.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3263bf6a..dcb625626 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -316,6 +316,98 @@ export const handlers = [ Don't forget to re-run the `.storybook/generate.js` script after adding, editing, or removing the above files. +## Nest + +### Nest Service Circular dependency / Nestでサービスの循環参照でエラーが起きた場合 + +#### forwardRef +まずは簡単に`forwardRef`を試してみる + +```typescript +export class FooService { + constructor( + @Inject(forwardRef(() => BarService)) + private barService: BarService + ) { + } +} +``` + +#### OnModuleInit +できなければ`OnModuleInit`を使う + +```typescript +import { Injectable, OnModuleInit } from '@nestjs/common'; +import { ModuleRef } from '@nestjs/core'; +import { BarService } from '@/core/BarService'; + +@Injectable() +export class FooService implements OnModuleInit { + private barService: BarService // constructorから移動してくる + + constructor( + private moduleRef: ModuleRef, + ) { + } + + async onModuleInit() { + this.barService = this.moduleRef.get(BarService.name); + } + + public async niceMethod() { + return await this.barService.incredibleMethod({ hoge: 'fuga' }); + } +} +``` + +##### Service Unit Test +テストで`onModuleInit`を呼び出す必要がある + +```typescript +// import ... + +describe('test', () => { + let app: TestingModule; + let fooService: FooService; // for test case + let barService: BarService; // for test case + + beforeEach(async () => { + app = await Test.createTestingModule({ + imports: ..., + providers: [ + FooService, + { // mockする (mockは必須ではないかもしれない) + provide: BarService, + useFactory: () => ({ + incredibleMethod: jest.fn(), + }), + }, + { // Provideにする + provide: BarService.name, + useExisting: BarService, + }, + ], + }) + .useMocker(... + .compile(); + + fooService = app.get(FooService); + barService = app.get(BarService) as jest.Mocked; + + // onModuleInitを実行する + await fooService.onModuleInit(); + }); + + test('nice', () => { + await fooService.niceMethod(); + + expect(barService.incredibleMethod).toHaveBeenCalled(); + expect(barService.incredibleMethod.mock.lastCall![0]) + .toEqual({ hoge: 'fuga' }); + }); +}) +``` + ## Notes ### Misskeyのドメイン固有の概念は`Mi`をprefixする