import { NestFactory } from '@nestjs/core';
import { RunnerModule } from './runner.module';
async function bootstrap() {
const app = await NestFactory.create(RunnerModule);
await app.listen(3000);
}
bootstrap();
所以这是主要的ts。我想测试它,但我不知道如何测试该应用程序正在侦听端口 3000 模拟路径
该文件中没有任何可测试的内容。
相反,您可以为
RunnerModule
编写集成测试,就像文档中显示的 E2E 测试一样。
我不明白为什么你想测试服务器是否正在监听某个端口,因为这段逻辑不是你写的,这是框架应该注意的。
如果您的
main.ts
如下所示:
import { NestFactory } from '@nestjs/core';
import { ConfigService } from '@nestjs/config';
import { NestExpressApplication } from '@nestjs/platform-express';
import { AppModule } from 'app.module';
import { configureApp } from 'app.config';
export async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
/**
* All app configuration should be added to `configApp` for re-use within integration/e2e tests.
*/
configureApp({ app });
const configService = app.get(ConfigService);
await app.listen(configService.get('APPLICATION_PORT', 3000), '0.0.0.0');
}
void bootstrap();
您可以通过执行以下操作来测试这一点。另请注意,由于存在对
bootstrap
的调用,因此您的模拟可能会被多次调用。
import { createMock } from '@golevelup/ts-jest';
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { configureApp } from 'app.config';
import { bootstrap } from 'main';
jest.mock('@nestjs/core', () => ({
__esModule: true,
default: jest.fn(),
NestFactory: {
create: jest.fn().mockResolvedValue(createMock<NestExpressApplication>()),
},
}));
jest.mock('app.module');
jest.mock('app.config');
describe('App Bootstrap', () => {
it('it bootstraps and launches the application', async () => {
await bootstrap();
const factoryCreateSpy = jest.spyOn(NestFactory, 'create');
expect(factoryCreateSpy).toHaveBeenCalled();
expect(configureApp).toHaveBeenCalled();
});
});
我的
entry.ts
文件中有更多逻辑,因此我需要一种更具包容性的方法。我稍微调整了 coler-j 的答案,并将我的入口点引导程序和全局配置分开。
我的 Nest 应用程序名为
,所以大部分命名都以main-api
开头main-api*
src/main-api-entry.ts
import { NestFactory } from '@nestjs/core';
import { ConfigService } from '@nestjs/config';
import { MainApiModule } from './main-api.module';
import { IMainAppConfig } from 'shared/types';
import { configureMainApiNestApp } from './main-api-bootstrap-config';
async function bootstrap () {
const app = await NestFactory.create(MainApiModule, {
cors: true,
bufferLogs: true
});
/* call through to global config in separate file */
configureMainApiNestApp(app);
const configService = app.get<ConfigService<IMainAppConfig, true>>(ConfigService);
await app.listen(configService.get('APP_PORT'));
console.info('Starting app...', {
apiBase: configService.get('API_BASE'),
port: configService.get('APP_PORT'),
isProd: configService.get('IS_PROD'),
url: (await app.getUrl())?.replace('[::1]', 'localhost')
});
}
bootstrap();
src/main-api-bootstrap-config.ts
import * as cookieParser from 'cookie-parser';
import { INestApplication, ValidationPipe, VersioningType } from '@nestjs/common';
import { Application as ExpressApplication } from 'express';
/* app specific files */
import { appExceptionFactory, AllExceptionsFilter } from 'shared/errors';
import { GlobalAuthGuard } from 'shared/auth';
export function configureMainApiNestApp (
app: INestApplication
) {
const expressApp = app.getHttpAdapter() as any as ExpressApplication;
app.useGlobalGuards(app.get(GlobalAuthGuard));
/* validation errors get caught by this pipe */
/* see: https://docs.nestjs.com/techniques/validation */
app.useGlobalPipes(new ValidationPipe({
stopAtFirstError: false,
transform: true,
whitelist: true,
exceptionFactory: appExceptionFactory
}));
app.useGlobalFilters(app.get(AllExceptionsFilter));
/* general api stuff */
expressApp.disable('x-powered-by');
app.use(cookieParser());
app.setGlobalPrefix('api');
app.enableVersioning({
type: VersioningType.URI,
prefix: 'v',
defaultVersion: '4'
});
return app;
}
测试/e2e/app.e2e.test.ts
import { Test, TestingModule } from '@nestjs/testing';
import { HttpStatus, INestApplication } from '@nestjs/common';
import * as request from 'supertest';
/* these import paths are project specific */
import { MainApiModule } from '../../src/main-api.module';
import { configureMainApiNestApp } from '../../src/main-api-bootstrap-config';
describe('MainApiModule (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [MainApiModule]
}).compile();
app = moduleFixture.createNestApplication();
/* configure global config for my test app instance */
configureMainApiNestApp(app);
await app.init();
});
it('GET /api/v4/test/auth', () => {
return request(app.getHttpServer())
/* `/api/v4` prefix and version is correct from global config */
.get('/api/v4/test/auth')
/* global auth is setup (this is an app specific endpoint) */
.expect(HttpStatus.UNAUTHORIZED);
});
});