typescript - NestJS测试: decorator is not a function

标签 typescript testing jestjs decorator nestjs

我的依赖项:

"@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 切换过来至@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';

我尝试添加到 my.service.ts之前MyService声明:

console.log('InjectDatabase', InjectDatabase)

并收到:

InjectDatabase: undefined

看来 Jest 无法解析导入或者 typescript 配置有问题。

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"对于 "@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" 正在返回undefined 当路径如下: import Stuff from "@infra 效果非常好。

我修复了@infra中的桶文件lib 正确导出内容并修复导入以使用缩短路径,这有助于解决问题。

我还是很好奇为什么要设置 Jest: "@infra/(.*)": "<rootDir>/libs/infrastructure/src/$1" 在下面: moduleNameMapper 不起作用。

关于typescript - NestJS测试: decorator is not a function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64214984/

相关文章:

javascript - 为 Typescript 中的 Angular Directive(指令)错误键入服务对象

javascript - 如何使用 Typescript 创建 Jest 自定义环境?

reactjs - 如何使用 jest 测试 React 类中除渲染之外的函数?

c# - 当前上下文中不存在名称 'AutomationId'

javascript - React Redux 应用程序中 Windows 10 上的 Jest "No tests found, exiting with code 1"错误

javascript - Angular Reactive Forms - 排除表单提交上的空白字段

javascript - Typescript React/Redux 指南 - 如何从 js 翻译?

javascript - Sequelize/ typescript : Types of parameters 'values' and 'values' are incompatible

ruby-on-rails - Rake 测试仅在测试环境中失败

django:运行覆盖测试