如何在不连接数据库的情况下在 nestjs 和 typeorm 中编写单元测试

How to write unit test in nestjs and typeorm without connecting to db

我不确定如何在不连接到数据库的情况下在 nestjs 和 typeorm 中实现单元测试。我尝试了很多技术,但似乎都没有用。

我的模块看起来像这样。

import { HttpModule, Module } from '@nestjs/common'
import moment from 'moment';

import config from '@app/config'
import { OrdersService } from './services/order.service'
import { FraudOrderChecksService } from './services/fraud-order-checks.service'
import { FraudOrderChecksController } from './controllers/fraud-order-checks.controller'
import { HealthcheckController } from './controllers/healthcheck.controller';
import { TypeOrmModule } from '@nestjs/typeorm'
import { ormconfig } from './entities/ormconfig'


@Module({
    imports: [
        SharedModule,
        HttpModule,
        LoggerModule,
        ConfigModule.forRoot(config),
        TypeOrmModule.forRoot(ormconfig.luminskin as any),
        TypeOrmModule.forRoot(ormconfig.meridian as any),
        TypeOrmModule.forFeature([...ormconfig.luminskin.entities], 'luminskin'),
        TypeOrmModule.forFeature([...ormconfig.meridian.entities], 'meridian'),
        ...
    ],
    controllers: [
        MyController,
        ...
    ],
    providers: [
        ...
    ],
})
export class AppModule { }

我在测试中导入根模块

  beforeEach(async () => {
    jest.clearAllMocks();
    const module: TestingModule = await Test.createTestingModule({
      imports: [InternalModule]
    }).compile();
    ...
  });

当我尝试 运行 我的单元测试时,我得到

[Nest] 93196   - 06/04/2021, 17:43:50   [ExceptionHandler] Unable to connect to the database (mydb). Retrying (1)...
AlreadyHasActiveConnectionError: Cannot create a new connection named "connectionname", because connection with such name already exist and it now has an active connection session.

如何将连接与根模块解耦,以便仅在需要时 运行。其实cleaner technic也会被接受

您不想对模块进行单元测试,而是希望对模块的各个组件进行单独的单元测试。

尽管您可以 创建一个 TestModule 并像上面那样简单地导入您的模块,但我只会在模块包含单个组件时才考虑这样做(即使那样我也不会因为我认为这不是很好的做法)。

您带入测试的组件越多:

  • 您需要管理的活动部件越多
  • 你要嘲笑的越多
  • 单元及其测试的便携性越差
  • 你摄入的阿司匹林越多,尝试解决每次修改其父模块时发生的自我诱发的头痛

Nests TestingModule 使您能够以隔离测试您的组件 所需的最低限度“装配”一个独立模块。它简化了您的测试设置和模拟 creation/management.

始终尝试将单元测试视为一个独立的、独立的过程。尽可能限制范围和依赖性,以使测试尽可能有效和简单。

这是我对服务进行单元测试时所采用的方法示例,我模拟了它的依赖项:

// app.service.spec.ts

describe('Testing app.service', () => {
  let module: TestingModule;
  let service: AppService;

  // mock out providers the service depends on
  const mockProviders = [
    {
      provide: ConfigService,
      useValue: {
        get: jest.fn().mockReturnValue('Mock!'),
      },
    },
  ];

  beforeAll(async () => {
    // build up testing module
    module = await Test.createTestingModule({
      imports: [],
      providers: [...mockProviders, AppService],
    })
      .compile()
      .catch((err) => {
        // Helps catch ninja like errors from compilation
        console.error(err);
        throw err;
      });

    service = module.get<AppService>(AppService);
  });

  it('Should return: Hello Mock!', async () => {
    const response = service.getHello();
    expect(response).toEqual('Hello Mock');
  });
});

我尝试将所有业务逻辑(尽可能)保留在服务中,让控制器保持轻便,通常保留用于 e2e and/or 集成测试。

这不是唯一(甚至可能不是“最佳”)方法,但它可以帮助我更加专注于测试和服务。