86 lines
2.7 KiB
TypeScript
86 lines
2.7 KiB
TypeScript
import type { INestApplication } from '@nestjs/common';
|
|
import { Test } from '@nestjs/testing';
|
|
import request from 'supertest';
|
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
|
|
import { HealthController } from '../src/health.controller';
|
|
import {
|
|
HealthService,
|
|
MYSQL_HEALTH_PORT,
|
|
REDIS_HEALTH_PORT,
|
|
type DependencyHealthPort,
|
|
} from '../src/health.service';
|
|
|
|
describe('GET /api/v1/health', () => {
|
|
let app: INestApplication | undefined;
|
|
|
|
afterEach(async () => {
|
|
await app?.close();
|
|
app = undefined;
|
|
});
|
|
|
|
async function createApp(
|
|
redis: DependencyHealthPort,
|
|
mysql: DependencyHealthPort,
|
|
): Promise<INestApplication> {
|
|
const moduleRef = await Test.createTestingModule({
|
|
controllers: [HealthController],
|
|
providers: [
|
|
HealthService,
|
|
{ provide: REDIS_HEALTH_PORT, useValue: redis },
|
|
{ provide: MYSQL_HEALTH_PORT, useValue: mysql },
|
|
],
|
|
}).compile();
|
|
const nestApp = moduleRef.createNestApplication();
|
|
nestApp.setGlobalPrefix('api/v1');
|
|
await nestApp.init();
|
|
return nestApp;
|
|
}
|
|
|
|
it('依赖健康时返回 200 与 RocketMQ disabled', async () => {
|
|
app = await createApp(
|
|
{ check: async () => ({ status: 'healthy', detail: 'PONG' }) },
|
|
{ check: async () => ({ status: 'healthy', detail: 'MySQL 5.7' }) },
|
|
);
|
|
|
|
const response = await request(app.getHttpServer()).get('/api/v1/health').expect(200);
|
|
|
|
expect(response.body).toMatchObject({
|
|
status: 'healthy',
|
|
process: 'api',
|
|
dependencies: {
|
|
redis: { status: 'healthy' },
|
|
mysql: { status: 'healthy' },
|
|
rocketMq: { status: 'disabled' },
|
|
},
|
|
});
|
|
});
|
|
|
|
it('依赖失败时返回 503 且不泄漏错误中的敏感值', async () => {
|
|
app = await createApp(
|
|
{ check: async () => ({ status: 'unavailable', detail: 'TEST_SENSITIVE_VALUE' }) },
|
|
{ check: async () => ({ status: 'healthy', detail: 'MySQL 5.7' }) },
|
|
);
|
|
|
|
const response = await request(app.getHttpServer()).get('/api/v1/health').expect(503);
|
|
const serialized = JSON.stringify(response.body);
|
|
|
|
expect(response.body.status).toBe('unavailable');
|
|
expect(serialized).not.toContain('TEST_SENSITIVE_VALUE');
|
|
});
|
|
|
|
it('有意禁用的可选依赖不降低 API 总体状态', async () => {
|
|
app = await createApp(
|
|
{ check: async () => ({ status: 'healthy', detail: 'PONG' }) },
|
|
{ check: async () => ({ status: 'disabled', detail: 'MySQL 未启用' }) },
|
|
);
|
|
|
|
const response = await request(app.getHttpServer()).get('/api/v1/health').expect(200);
|
|
|
|
expect(response.body).toMatchObject({
|
|
status: 'healthy',
|
|
dependencies: { mysql: { status: 'disabled' } },
|
|
});
|
|
});
|
|
});
|