| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
- import { DataSource } from 'typeorm';
- import * as cron from 'node-cron';
- import { DelaySchedulerService } from '../../src/services/delay-scheduler.service';
- import type { FeieApiConfig } from '../../src/types/feie.types';
- // Mock dependencies
- vi.mock('../../src/services/print-task.service', () => {
- return {
- PrintTaskService: vi.fn().mockImplementation(() => ({
- getPendingDelayedTasks: vi.fn().mockResolvedValue([]),
- executePrintTask: vi.fn().mockResolvedValue({})
- }))
- };
- });
- vi.mock('node-cron', () => {
- return {
- schedule: vi.fn().mockReturnValue({
- start: vi.fn(),
- stop: vi.fn()
- })
- };
- });
- describe('DelaySchedulerService', () => {
- let delaySchedulerService: DelaySchedulerService;
- let mockDataSource: DataSource;
- const mockFeieConfig: FeieApiConfig = {
- baseUrl: 'http://api.feieyun.cn/Api/Open/',
- user: 'test_user',
- ukey: 'test_ukey'
- };
- beforeEach(() => {
- vi.clearAllMocks();
- vi.useFakeTimers();
- mockDataSource = {
- getRepository: vi.fn().mockImplementation(() => {
- throw new Error('Repository not found');
- }),
- query: vi.fn().mockResolvedValue([])
- } as any;
- delaySchedulerService = new DelaySchedulerService(mockDataSource, mockFeieConfig);
- });
- afterEach(() => {
- vi.useRealTimers();
- });
- describe('constructor', () => {
- it('应该创建调度器实例', () => {
- expect(delaySchedulerService).toBeInstanceOf(DelaySchedulerService);
- });
- it('应该设置默认延迟时间为120秒', () => {
- expect(delaySchedulerService.getDefaultDelaySeconds()).toBe(120);
- });
- });
- describe('start', () => {
- it('应该启动调度器', async () => {
- await delaySchedulerService.start();
- expect(cron.schedule).toHaveBeenCalledWith('*/30 * * * * *', expect.any(Function));
- expect(delaySchedulerService.getStatus().isRunning).toBe(true);
- });
- it('应该在调度器已在运行时抛出错误', async () => {
- await delaySchedulerService.start();
- await expect(delaySchedulerService.start())
- .rejects
- .toThrow('调度器已经在运行中');
- });
- });
- describe('stop', () => {
- it('应该停止调度器', async () => {
- await delaySchedulerService.start();
- await delaySchedulerService.stop();
- expect(delaySchedulerService.getStatus().isRunning).toBe(false);
- });
- it('应该在调度器未运行时抛出错误', async () => {
- await expect(delaySchedulerService.stop())
- .rejects
- .toThrow('调度器未在运行中');
- });
- });
- describe('setDefaultDelaySeconds', () => {
- it('应该设置默认延迟时间', () => {
- delaySchedulerService.setDefaultDelaySeconds(180);
- expect(delaySchedulerService.getDefaultDelaySeconds()).toBe(180);
- });
- it('应该在延迟时间为负数时抛出错误', () => {
- expect(() => delaySchedulerService.setDefaultDelaySeconds(-1))
- .toThrow('延迟时间不能为负数');
- });
- });
- describe('getStatus', () => {
- it('应该返回调度器状态', () => {
- const status = delaySchedulerService.getStatus();
- expect(status).toEqual({
- isRunning: false,
- defaultDelaySeconds: 120,
- tenantId: null
- });
- });
- it('应该在调度器运行时返回正确状态', async () => {
- await delaySchedulerService.start();
- const status = delaySchedulerService.getStatus();
- expect(status.isRunning).toBe(true);
- expect(status.defaultDelaySeconds).toBe(120);
- });
- });
- describe('triggerManualProcess', () => {
- it('应该手动触发任务处理', async () => {
- const tenantId = 1;
- const mockTasks = [
- { taskId: 'TASK1', printerSn: 'PRINTER1' },
- { taskId: 'TASK2', printerSn: 'PRINTER2' }
- ];
- // Mock getPendingDelayedTasks to return tasks
- const mockPrintTaskService = {
- getPendingDelayedTasks: vi.fn().mockResolvedValue(mockTasks),
- executePrintTask: vi.fn().mockResolvedValue({})
- };
- (delaySchedulerService as any).printTaskService = mockPrintTaskService;
- const result = await delaySchedulerService.triggerManualProcess(tenantId);
- expect(result).toEqual({
- success: true,
- processedTasks: 2,
- message: '成功处理 2 个延迟打印任务'
- });
- expect(mockPrintTaskService.getPendingDelayedTasks).toHaveBeenCalledWith(tenantId);
- expect(mockPrintTaskService.executePrintTask).toHaveBeenCalledTimes(2);
- });
- it('应该在处理失败时返回错误信息', async () => {
- const tenantId = 1;
- // Mock getPendingDelayedTasks to throw error
- const mockPrintTaskService = {
- getPendingDelayedTasks: vi.fn().mockRejectedValue(new Error('数据库错误'))
- };
- (delaySchedulerService as any).printTaskService = mockPrintTaskService;
- const result = await delaySchedulerService.triggerManualProcess(tenantId);
- expect(result).toEqual({
- success: false,
- processedTasks: 0,
- message: '手动处理失败: 数据库错误'
- });
- });
- });
- describe('healthCheck', () => {
- it('应该返回健康状态', async () => {
- const health = await delaySchedulerService.healthCheck();
- expect(health).toEqual({
- healthy: false,
- isRunning: false,
- timestamp: expect.any(Date)
- });
- });
- it('应该在调度器运行时返回健康状态', async () => {
- await delaySchedulerService.start();
- const health = await delaySchedulerService.healthCheck();
- expect(health).toEqual({
- healthy: true,
- isRunning: true,
- timestamp: expect.any(Date)
- });
- });
- });
- describe('processDelayedTasks', () => {
- it('应该处理延迟任务', async () => {
- // 由于processDelayedTasks是私有方法,我们通过start方法来测试
- // 当调度器启动时,它会定期调用processDelayedTasks
- await delaySchedulerService.start();
- // 手动触发一次处理
- const scheduleCallback = vi.mocked(cron.schedule).mock.calls[0][1];
- await scheduleCallback();
- // 验证处理逻辑被调用
- expect(true).toBe(true);
- });
- it('应该在处理失败时记录错误', async () => {
- const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
- // Mock getTenantsWithDelayedTasks to throw error
- const originalGetTenantsWithDelayedTasks = (delaySchedulerService as any).getTenantsWithDelayedTasks;
- (delaySchedulerService as any).getTenantsWithDelayedTasks = vi.fn().mockRejectedValue(new Error('处理失败'));
- await delaySchedulerService.start();
- const scheduleCallback = vi.mocked(cron.schedule).mock.calls[0][1];
- await scheduleCallback();
- expect(consoleErrorSpy).toHaveBeenCalledWith('处理延迟打印任务失败:', expect.any(Error));
- // Restore
- (delaySchedulerService as any).getTenantsWithDelayedTasks = originalGetTenantsWithDelayedTasks;
- consoleErrorSpy.mockRestore();
- });
- });
- });
|