Files
ai-learning-platform/backend/src/modules/ai/tests/ai-gateway.service.spec.ts
T
yuzhiran-dev 6f3fe50ee0 docs & cleanup: update stack info, remove dead code, fix backend bugs
- Fix AGENTS.md and 技术架构设计.md to reflect actual stack (Prisma+MySQL, static export, PM2)
- Remove 4 unused frontend components (page-transition, page-layout, image-upload, section-card)
- Fix card.tsx hardcoded colors → CSS variables
- Remove provider name from model selector, remove sensenova-u1-fast from models
- Fix analytics.controller.ts raw SQL table names (runtime bug)
- Add JWT auth guard to tools POST endpoint
- Fix AI gateway test: update env vars and model names
- Fix admin test: mock role structure for Prisma relation
2026-05-29 10:26:50 +08:00

132 lines
4.0 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import { AIGatewayService } from '../ai-gateway.service';
describe('AIGatewayService', () => {
let service: AIGatewayService;
beforeEach(async () => {
// Clear env before each test
delete process.env.OPENAI_API_KEY;
delete process.env.SENSENOVA_API_KEY;
const module: TestingModule = await Test.createTestingModule({
providers: [AIGatewayService],
}).compile();
service = module.get<AIGatewayService>(AIGatewayService);
});
describe('initialization', () => {
it('should have no providers when no API keys set', () => {
const providers = service.getRegisteredProviders();
expect(providers).toEqual([]);
});
});
describe('fallback mock responses', () => {
it('should greet when asked "你好"', async () => {
const result = await service.chat('any-model', [
{ role: 'user', content: '你好' },
]);
expect(result).toContain('你好!我是宇之然 AI 助手');
});
it('should greet in English for "hello"', async () => {
const result = await service.chat('any-model', [
{ role: 'user', content: 'hello' },
]);
expect(result).toContain('Hello! I am YuZhiRan AI assistant');
});
it('should provide prompt tips when asked about 提示词', async () => {
const result = await service.chat('any-model', [
{ role: 'user', content: '如何写好提示词?' },
]);
expect(result).toContain('明确角色');
expect(result).toContain('输出格式');
});
it('should provide model info when asked about 大模型', async () => {
const result = await service.chat('any-model', [
{ role: 'user', content: '有哪些大模型?' },
]);
expect(result).toContain('GPT');
expect(result).toContain('Claude');
expect(result).toContain('DeepSeek');
});
it('should return generic fallback for unknown queries', async () => {
const result = await service.chat('any-model', [
{ role: 'user', content: '今天的天气怎么样?' },
]);
expect(result).toContain('模拟模式');
expect(result).toContain('API Key');
});
});
describe('model routing', () => {
it('should route deepseek-v4-flash to its provider (but fallback to mock)', async () => {
const result = await service.chat('deepseek-v4-flash', [
{ role: 'user', content: '你好' },
]);
// Falls back to mock since no API key
expect(result).toContain('宇之然 AI 助手');
});
it('should route general model to openai provider (but fallback to mock)', async () => {
const result = await service.chat('general', [
{ role: 'user', content: '你好' },
]);
expect(result).toContain('宇之然 AI 助手');
});
it('should handle unknown model names by falling back', async () => {
const result = await service.chat('unknown-model-xyz', [
{ role: 'user', content: '测试' },
]);
expect(result).toContain('模拟模式');
});
});
describe('contextual fallback', () => {
it('should include user message in fallback response', async () => {
const result = await service.chat('any', [
{ role: 'user', content: '如何学习 Python 编程?' },
]);
expect(result).toContain('Python');
});
it('should handle multi-turn conversations', async () => {
const messages = [
{ role: 'user' as const, content: '你是谁?' },
{ role: 'assistant' as const, content: '我是 AI 助手。' },
{ role: 'user' as const, content: '提示词有什么技巧?' },
];
const result = await service.chat('any', messages);
expect(result).toContain('提示词');
});
it('should truncate long user messages', async () => {
const longMsg = 'a'.repeat(200);
const result = await service.chat('any', [
{ role: 'user', content: longMsg },
]);
expect(result).toContain('...');
});
});
});