feat: 支持单元测试

This commit is contained in:
richarjiang
2026-04-08 16:02:19 +08:00
parent 2d0fee8a9a
commit df05b7280c
18 changed files with 2462 additions and 17 deletions

View File

@@ -1,41 +1,69 @@
import { Test, TestingModule } from '@nestjs/testing';
import { NotFoundException } from '@nestjs/common';
import { WechatGameService } from './wechat-game.service';
import { GameConfigRepository } from './repositories/game-config.repository';
import { NotFoundException } from '@nestjs/common';
import { LevelRepository } from './repositories/level.repository';
import { GameConfig } from './entities/game-config.entity';
import { Level } from './entities/level.entity';
describe('WechatGameService', () => {
let service: WechatGameService;
let repository: GameConfigRepository;
const mockGameConfig: GameConfig = {
id: 'test-uuid',
id: 'config-uuid-1',
configKey: 'game_speed',
configValue: '1.5',
description: 'Game speed multiplier',
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
createdAt: new Date('2026-01-01'),
updatedAt: new Date('2026-01-01'),
};
const mockRepository = {
const mockLevel: Level = {
id: 'level-1',
imageUrl: 'https://example.com/meme1.jpg',
answer: '答案一',
hint1: '提示1',
hint2: '提示2',
hint3: null,
sortOrder: 0,
timeLimit: 60,
createdAt: new Date('2026-01-01'),
updatedAt: new Date('2026-01-01'),
};
const mockLevel2: Level = {
id: 'level-2',
imageUrl: 'https://example.com/meme2.jpg',
answer: '答案二',
hint1: '提示A',
hint2: null,
hint3: null,
sortOrder: 1,
timeLimit: null,
createdAt: new Date('2026-01-01'),
updatedAt: new Date('2026-01-01'),
};
const mockGameConfigRepository = {
findActiveConfigs: jest.fn(),
findByKey: jest.fn(),
};
const mockLevelRepository = {
findAllOrdered: jest.fn(),
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
WechatGameService,
{
provide: GameConfigRepository,
useValue: mockRepository,
},
{ provide: GameConfigRepository, useValue: mockGameConfigRepository },
{ provide: LevelRepository, useValue: mockLevelRepository },
],
}).compile();
service = module.get<WechatGameService>(WechatGameService);
repository = module.get<GameConfigRepository>(GameConfigRepository);
});
afterEach(() => {
@@ -44,18 +72,20 @@ describe('WechatGameService', () => {
describe('getAllConfigs', () => {
it('should return all active configs', async () => {
mockRepository.findActiveConfigs.mockResolvedValue([mockGameConfig]);
mockGameConfigRepository.findActiveConfigs.mockResolvedValue([
mockGameConfig,
]);
const result = await service.getAllConfigs();
expect(result.configs).toHaveLength(1);
expect(result.total).toBe(1);
expect(result.configs[0].configKey).toBe('game_speed');
expect(mockRepository.findActiveConfigs).toHaveBeenCalled();
expect(result.configs[0].configValue).toBe('1.5');
});
it('should return empty array when no configs found', async () => {
mockRepository.findActiveConfigs.mockResolvedValue([]);
mockGameConfigRepository.findActiveConfigs.mockResolvedValue([]);
const result = await service.getAllConfigs();
@@ -66,21 +96,74 @@ describe('WechatGameService', () => {
describe('getConfigByKey', () => {
it('should return config by key', async () => {
mockRepository.findByKey.mockResolvedValue(mockGameConfig);
mockGameConfigRepository.findByKey.mockResolvedValue(mockGameConfig);
const result = await service.getConfigByKey('game_speed');
expect(result.configKey).toBe('game_speed');
expect(result.configValue).toBe('1.5');
expect(mockRepository.findByKey).toHaveBeenCalledWith('game_speed');
expect(mockGameConfigRepository.findByKey).toHaveBeenCalledWith(
'game_speed',
);
});
it('should throw NotFoundException when config not found', async () => {
mockRepository.findByKey.mockResolvedValue(null);
mockGameConfigRepository.findByKey.mockResolvedValue(null);
await expect(service.getConfigByKey('nonexistent')).rejects.toThrow(
NotFoundException,
);
});
});
describe('getAllLevels', () => {
it('should return all levels with 1-indexed level numbers', async () => {
mockLevelRepository.findAllOrdered.mockResolvedValue([
mockLevel,
mockLevel2,
]);
const result = await service.getAllLevels();
expect(result.levels).toHaveLength(2);
expect(result.total).toBe(2);
expect(result.levels[0].level).toBe(1);
expect(result.levels[0].id).toBe('level-1');
expect(result.levels[0].answer).toBe('答案一');
expect(result.levels[1].level).toBe(2);
expect(result.levels[1].id).toBe('level-2');
});
it('should return empty array when no levels exist', async () => {
mockLevelRepository.findAllOrdered.mockResolvedValue([]);
const result = await service.getAllLevels();
expect(result.levels).toHaveLength(0);
expect(result.total).toBe(0);
});
});
describe('getLevelById', () => {
it('should return level with correct level number', async () => {
mockLevelRepository.findAllOrdered.mockResolvedValue([
mockLevel,
mockLevel2,
]);
const result = await service.getLevelById('level-2');
expect(result.id).toBe('level-2');
expect(result.level).toBe(2);
expect(result.answer).toBe('答案二');
});
it('should throw NotFoundException when level not found', async () => {
mockLevelRepository.findAllOrdered.mockResolvedValue([mockLevel]);
await expect(service.getLevelById('nonexistent')).rejects.toThrow(
NotFoundException,
);
});
});
});