簡體   English   中英

NestJS 測試:裝飾器不是函數

[英]NestJS Testing: decorator is not a function

我的依賴:

"@nestjs/common": "7.4.4",
"@nestjs/core": "7.4.4",
"typescript": "4.0.2",
"jest": "26.4.2",
"jest-junit": "11.1.0",
"ts-jest": "26.3.0",

我有一個自定義裝飾器:

import { Inject } from "@nestjs/common";

import { DATABASE_SERVICE } from "./database.constants";

export const InjectDatabase = () => Inject(DATABASE_SERVICE);

我在構造函數中使用它來提供我願意用測試覆蓋的服務:

import {
  DatabaseService,
  InjectDatabase
} from "@infra/modules";
import { Injectable } from "@nestjs/common";

@Injectable()
export class MyService {
  constructor(
    @InjectDatabase() private readonly db: DatabaseService
  ) {}
}

這是我設置測試模塊的方法:

import { Test } from "@nestjs/testing";

import { MyService } from "../../../src/shared/services/my.service";
import { SharedModule } from "../../../src/shared/shared.module";

describe(`MyService`, () => {
  let myService: MyService;

  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      imports: [SharedModule]
    }).compile();

    myService = moduleRef.get<MyService>(MyService);
  });
  test("tests", () => {
    // console.log("test");
  });
});

SharedModule 是一個帶有@Global()裝飾器的模塊,並在提供者/導出中包含MyService

當我嘗試執行測試時,出現錯誤:

TypeError: modules_1.InjectDatabase is not a function

      51 | 
      52 |   constructor(
    > 53 |     @InjectDatabase() private readonly adb_db: DatabaseService,
         |      ^
      56 |   ) {}

      at Object.<anonymous> (apps/workers/my/src/shared/services/my.service.ts:53:6)
      at Object.<anonymous> (apps/workers/my/test/shared/services/my.service.unit.test.ts:8:1)

我遵循了上面的跟蹤和步驟:

  • 在測試中使用服務導入文件: import { MyService } from "../../../src/shared/services/my.service";
  • 在服務構造函數中的@InjectDatabase()@InjectDatabase()錯誤

如果我從@InjectDatabase切換到@Inject(DATABASE_SERVICE)

@Injectable()
export class MyService {
  constructor(
    @Inject(DATABASE_SERVICE) private readonly db: DatabaseService
  ) {}
}

我收到另一個錯誤:

Error: Nest can't resolve dependencies of the CacheService (?). Please make sure that the argument dependency at index [0] is available in the RootTestModule context.

我嘗試像這樣設置測試模塊:

    const moduleRef = await Test.createTestingModule({
      imports: [DatabaseModule],
      providers: [
        {
          provide: DATABASE_SERVICE,
          useClass: DatabaseService
        },
        MyService
      ]
    }).compile();

但這沒有幫助,同樣的問題:

Error: Nest can't resolve dependencies of the CacheService (?).

我的tsconfig.json編譯器選項:

  "compilerOptions": {
    "target": "es2018",
    "module": "commonjs",
    "outDir": "dist/",
    "esModuleInterop": true,
    "strict": true,
    "sourceRoot": "/",
    "sourceMap": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "strictPropertyInitialization": false,
    "removeComments": true,
    "resolveJsonModule": true
  }

我在jest.config.js

setupFiles: ["./jest-setup-file.ts"],

這個文件只導入了反射庫:

import 'reflect-metadata';

我嘗試在MyService聲明之前添加到my.service.ts

console.log('InjectDatabase', InjectDatabase)

並收到:

InjectDatabase: undefined

因此,似乎 Jest 無法解析導入 o 打字稿配置有問題。

MyService導入的裝飾器函數為:

import {
  DatabaseService,
  InjectDatabase
} from "@infra/modules";

我的jest.config.js

module.exports = {
  bail: 0,
  verbose: true,
  preset: "ts-jest",
  testEnvironment: "node",
  roots: ["<rootDir>/libs", "<rootDir>/apps"],
  testRegex: ".*\\.test\\.ts$",
  testPathIgnorePatterns: ["/node_modules/", "/dist/", "/build/"],
  moduleFileExtensions: ["ts", "js", "json"],
  moduleNameMapper: {
    "@common": "<rootDir>/libs/common/src",
    "@common/(.*)": "<rootDir>/libs/common/src/$1",
    "@infra": "<rootDir>/libs/infrastructure/src",
    "@infra/(.*)": "<rootDir>/libs/infrastructure/src/$1"
  },
  transform: {
    "^.+\\.ts?$": "ts-jest"
  },
  setupFiles: ["./jest-setup-file.ts"],
  collectCoverage: true,
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    }
  },
  coverageReporters: ["json", "lcov", "text", "clover"],
  coveragePathIgnorePatterns: ["/node_modules/"]
};

可能moduleNameMapper沒有正確解析"@infra/(.*)": "<rootDir>/libs/infrastructure/src/$1" for "@infra/modules"

在測試之外 - 一切都按預期工作。

如何正確設置 jest/typescript/nest 以便正確識別我的自定義裝飾器?

經過更好的調試后,我發現 Jest 以某種方式無法將帶有子文件夾的路徑別名解析為模塊,而不是加載導入的內容,它返回未定義。 jest.config.js 中的設置:

    "@infra": "<rootDir>/libs/infrastructure/src",
    "@infra/(.*)": "<rootDir>/libs/infrastructure/src/$1"

所以上面的第二行不適用於 Jest。 所有具有以下路徑的import Stuff from "@infra/sub/folder/module"import Stuff from "@infra/sub/folder/module"返回undefined當路徑如下: import Stuff from "@infra工作就像一個魅力。

我在@infra lib 中修復了桶文件以正確導出內容並修復導入以使用縮短路徑,這有助於解決問題。

我仍然很好奇為什么設置 Jest: "@infra/(.*)": "<rootDir>/libs/infrastructure/src/$1" under: moduleNameMapper不起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM