使用 jest @ nestjs 运行 e2e 测试

xtr*_*nch 7 jestjs e2e-testing nestjs

我正在尝试使用 jest 和 nestjs 运行 e2e 测试,但遇到了最奇怪的错误,该错误在我的 google 搜索中没有返回任何内容(ExpressAdapter 不是构造函数):


    $ env-cmd -f .env.test jest --config ./test/jest-e2e.json
     FAIL  test/sensor.e2e-spec.ts (29.498 s)
      SensorController (e2e)
        × /sensors (GET) (15165 ms)

      ? SensorController (e2e) › /sensors (GET)

        Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.

          at mapper (../node_modules/jest-jasmine2/build/queueRunner.js:29:45)

      ? SensorController (e2e) › /sensors (GET)

        TypeError: Cannot read property 'getHttpServer' of undefined

          24 |
          25 |   it('/sensors (GET)', () => {
        > 26 |     return request(app.getHttpServer()).get('/sensors').expect(200);
             |                        ^
          27 |   });
          28 |
          29 |   afterAll(async () => {

          at Object.<anonymous> (sensor.e2e-spec.ts:26:24)

    Test Suites: 1 failed, 1 total
    Tests:       1 failed, 1 total
    Snapshots:   0 total
    Time:        29.69 s
    Ran all test suites.

    ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.

          17 |     }).compile();
          18 |
        > 19 |     app = moduleFixture.createNestApplication();
             |                         ^
          20 |
          21 |     await app.init();
          22 |     fixture = await SensorFixture(app);

          at ../node_modules/@nestjs/testing/testing-module.js:25:117
          at Object.loadPackage (../node_modules/@nestjs/common/utils/load-package.util.js:9:27)
          at TestingModule.createHttpAdapter (../node_modules/@nestjs/testing/testing-module.js:25:56)
          at TestingModule.createNestApplication (../node_modules/@nestjs/testing/testing-module.js:13:43)
          at Object.<anonymous> (sensor.e2e-spec.ts:19:25)
    (node:1500) UnhandledPromiseRejectionWarning: TypeError: Caught error after test environment was torn down

    ExpressAdapter is not a constructor
    (node:1500) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
    (node:1500) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    Jest did not exit one second after the test run has completed.

    This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.
    error Command failed with exit code 1.
    info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Run Code Online (Sandbox Code Playgroud)

我的 jest-e2e.json:


    {
      "moduleFileExtensions": ["js", "json", "ts"],
      "rootDir": ".",
      "testEnvironment": "node",
      "testRegex": ".e2e-spec.ts$",
      "transform": {
        "^.+\\.(t|j)s$": "ts-jest"
      },
      "moduleNameMapper": {
        "~(.*)$": "<rootDir>/../src/$1"
      }
    }


Run Code Online (Sandbox Code Playgroud)

jest.config.js:

    module.exports = {
      verbose: true,
      preset: 'ts-jest',
      rootDir: 'src',
      moduleNameMapper: {
        '~(.*)$': '<rootDir>/$1',
      },
      moduleFileExtensions: ['js', 'json', 'ts'],
      moduleDirectories: [
        "node_modules", 
        "src"
      ],
    };

Run Code Online (Sandbox Code Playgroud)

我正在使用 typeorm 并且我很确定我的测试数据库配置是正确的,因为我的单元测试执行没有问题(我正在针对实际的测试数据库运行它们)。

ormconfig.js:

module.exports = {
  type: process.env.DB_TYPE,
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  username: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_DATABASE,
  entities: process.env.DB_ENTITIES.split(' '),
  synchronize: process.env.DB_SYNCHRONIZE,
  autoLoadEntities: true,
  logging: process.env.DB_LOGGING,
}
Run Code Online (Sandbox Code Playgroud)

环境变量:

DB_TYPE = "postgres"
DB_HOST = "localhost"
DB_PORT = 5432
DB_USERNAME = "postgres"
DB_PASSWORD = "postgres"
DB_DATABASE = "sensor-dashboard-test"
DB_SYNCHRONIZE = true
DB_LOGGING = true
DB_ENTITIES = "**/*.entity{.ts,.js} ../src/modules/**/*.entity{.ts,.js}"
Run Code Online (Sandbox Code Playgroud)

我的依赖:

  "dependencies": {
    "@nestjs/common": "^7.0.0",
    "@nestjs/core": "^7.0.0",
    "@nestjs/platform-express": "^7.0.0",
    "@nestjs/typeorm": "^7.1.0",
    "class-transformer": "^0.2.3",
    "class-validator": "^0.12.2",
    "date-fns": "^2.15.0",
    "env-cmd": "^10.1.0",
    "nestjs-admin": "^0.4.0",
    "nestjs-typeorm-paginate": "^2.1.1",
    "pg": "^8.3.0",
    "postgres": "^1.0.2",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^6.5.4",
    "typeorm": "^0.2.25",
    "uuid": "^8.2.0"
  },
Run Code Online (Sandbox Code Playgroud)

以及失败的整个 e2e 测试:

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import {
  SensorFixtureInterface,
  SensorFixture,
} from '~modules/sensor/sensor.fixture';
import { AppModule } from '~app.module';

describe('SensorController (e2e)', () => {
  let app: INestApplication;
  let fixture: SensorFixtureInterface;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();

    await app.init();
    fixture = await SensorFixture(app);
  });

  it('/sensors (GET)', () => {
    return request(app.getHttpServer()).get('/sensors').expect(200);
  });

  afterAll(async () => {
    await app.close();
  });
});
Run Code Online (Sandbox Code Playgroud)

app.module.ts:

import { Module } from '@nestjs/common';
import { AppService } from './app.service';
import { SensorModule } from '~/modules/sensor/sensor.module';
import { DefaultAdminModule } from 'nestjs-admin';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MeasurementModule } from '~/modules/measurement/measurement.module';

@Module({
  imports: [
    SensorModule,
    MeasurementModule,
    DefaultAdminModule,
    TypeOrmModule.forRoot(),
  ],
  controllers: [],
  providers: [AppService],
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)

Link to the entire project: https://github.com/xtrinch/sensor-dashboard-nestjs-backend

小智 6

我遇到了同样的错误,并通过仅将 ts 文件(实体)传递到我的 typeorm 测试环境来修复它。

前任:

module.exports = {
  type: DB_TYPE,
  host: DB_HOST,
  port: DB_PORT,
  username: DB_USERNAME,
  password: DB_PASSWORD,
  database: DB_DATABASE,
  migrations: ['**/migrations/*.{ts,js}'],
  entities: NODE_ENV === 'test' ? ['**/*.entity.{ts}'] : ['**/*.entity.{ts,js}'],
  cli: {
    entitiesDir: 'src/database/entities',
    migrationsDir: 'src/database/migrations',
  },
};
Run Code Online (Sandbox Code Playgroud)