plugins/test-generator/skills/mock-generation/SKILL.md
生成测试所需的 Mock 数据与 Stub 函数。 当用户说"生成mock"、"创建mock"、"模拟数据"、"mock函数"、"stub函数"、"测试数据"、"模拟API"、"mock数据库"时使用此技能。 支持多框架 Mock:Jest (jest.fn/mock)、Vitest (vi.fn/vi.mock)、Python (unittest.mock/pytest-mock)。 生成 Mock 模块、Stub 函数、测试数据工厂、API 响应 Mock、数据库 Mock、时间 Mock。输出完整的 Mock 配置代码。
npx skillsauth add protagonistss/ithinku-plugins mock-generationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
这个技能专门负责生成测试所需的Mock数据和Stub函数,帮助隔离测试环境并提高测试效率。
// 为模块生成Mock
await generateMock('src/api/userService', {
framework: 'vitest',
includeReturnValues: true
});
// 为特定函数生成Mock
await generateFunctionMock('fetchUserData', {
returnType: 'User',
async: true,
errorScenarios: true
});
await generateMock(target, {
framework: 'vitest',
mockType: 'auto', // 'auto' | 'partial' | 'full'
includeSpies: true,
generateTestData: true,
customReturnValues: {
'getUser': () => ({ id: 1, name: 'Test User' }),
'createUser': () => Promise.resolve({ success: true })
}
});
// Mock整个模块
jest.mock('{{modulePath}}', () => ({
{{#each exports}}
{{name}}: jest.fn(),
{{/each}}
}));
// Mock实现
{{#each exports}}
{{name}}.mockImplementation(({{
#if isAsync}}
{{#if hasParams}}
async ({ {{join params ", "}} }) => {
// Mock implementation
return {{defaultValue}};
}
{{else}}
async () => {
return {{defaultValue}};
}
{{/if}}
{{else}}
{{#if hasParams}}
({ {{join params ", "}} }) => {
// Mock implementation
return {{defaultValue}};
}
{{else}}
() => {
return {{defaultValue}};
}
{{/if}}
{{/if}}
}));
{{/each}}
// 在测试中使用
beforeEach(() => {
{{#each exports}}
{{name}}.mockClear();
{{/each}}
});
import { vi } from 'vitest';
// Mock整个模块
vi.mock('{{modulePath}}', () => ({
{{#each exports}}
{{name}}: vi.fn(),
{{/each}}
}));
// Mock实现
{{#each exports}}
export const {{name}} = vi.fn();
{{#if isAsync}}
{{name}}.mockResolvedValue({{defaultValue}});
{{else}}
{{name}}.mockReturnValue({{defaultValue}});
{{/if}}
{{/each}}
from unittest.mock import Mock, patch
import pytest
{{#each functions}}
# Mock decorator
@patch('{{modulePath}}.{{name}}')
def test_{{testName}}(mock_{{name}}):
# Setup mock return value
mock_{{name}}.return_value = {{defaultValue}}
# Test implementation
result = function_under_test()
# Assertions
assert result is not None
{{#if verifyCalled}}
mock_{{name}}.assert_called_once()
{{/if}}
{{/each}}
class DataGenerator {
static generateString(options?: {
length?: number;
pattern?: string;
enum?: string[];
}): string {
if (options?.enum) {
return options.enum[0];
}
if (options?.pattern) {
return this.matchPattern(options.pattern);
}
const length = options?.length || 10;
return this.randomString(length);
}
static generateNumber(options?: {
min?: number;
max?: number;
integer?: boolean;
enum?: number[];
}): number {
if (options?.enum) {
return options.enum[0];
}
const min = options?.min || 0;
const max = options?.max || 100;
if (options?.integer) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
return Math.random() * (max - min) + min;
}
static generateArray<T>(itemGenerator: () => T, options?: {
length?: number;
minLength?: number;
maxLength?: number;
}): T[] {
const length = options?.length ||
Math.floor(Math.random() * (options?.maxLength || 5)) + (options?.minLength || 0);
return Array.from({ length }, itemGenerator);
}
static generateObject(schema: ObjectSchema): any {
const obj: any = {};
for (const [key, value] of Object.entries(schema)) {
if (typeof value === 'function') {
obj[key] = value();
} else if (Array.isArray(value)) {
obj[key] = this.generateArray(() => value[0]);
} else if (typeof value === 'object') {
obj[key] = this.generateObject(value);
} else {
obj[key] = value;
}
}
return obj;
}
}
// 用户对象生成器
const UserGenerator = {
generate: (overrides?: Partial<User>): User => ({
id: DataGenerator.generateNumber({ integer: true, min: 1 }),
name: DataGenerator.generateString({ length: 10 }),
email: DataGenerator.generateEmail(),
age: DataGenerator.generateNumber({ min: 18, max: 65, integer: true }),
isActive: true,
createdAt: new Date().toISOString(),
...overrides
}),
generateList: (count: number = 3): User[] =>
DataGenerator.generateArray(() => UserGenerator.generate(), { length: count }),
generateWithInvalidData: (): User => ({
id: -1,
name: '',
email: 'invalid-email',
age: -1,
isActive: false,
createdAt: 'invalid-date'
})
};
// API响应生成器
class APIResponseGenerator {
static generateSuccessResponse<T>(data: T): APIResponse<T> {
return {
success: true,
data,
message: 'Success',
timestamp: new Date().toISOString()
};
}
static generateErrorResponse(errorCode: string, message: string): APIResponse<null> {
return {
success: false,
data: null,
error: {
code: errorCode,
message,
details: {}
},
timestamp: new Date().toISOString()
};
}
static generatePaginatedResponse<T>(
items: T[],
page: number = 1,
limit: number = 10
): PaginatedResponse<T> {
return {
success: true,
data: items,
pagination: {
page,
limit,
total: items.length,
totalPages: Math.ceil(items.length / limit)
}
};
}
}
// Fetch Mock
const mockFetch = jest.fn();
mockFetch.mockImplementation(async (url: string, options?: RequestInit) => {
if (url.includes('/users')) {
return {
ok: true,
status: 200,
json: async () => APIResponseGenerator.generateSuccessResponse(
UserGenerator.generateList()
)
};
}
if (url.includes('/error')) {
return {
ok: false,
status: 500,
json: async () => APIResponseGenerator.generateErrorResponse(
'INTERNAL_ERROR',
'Something went wrong'
)
};
}
return {
ok: false,
status: 404,
json: async () => ({})
};
});
// 数据库连接Mock
const mockDb = {
users: {
findById: jest.fn(),
create: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
findMany: jest.fn()
},
transactions: {
begin: jest.fn(),
commit: jest.fn(),
rollback: jest.fn()
}
};
// 设置Mock返回值
mockDb.users.findById.mockImplementation(async (id: number) => {
if (id === 999) {
return null;
}
return UserGenerator.generate({ id });
});
mockDb.users.create.mockImplementation(async (userData: Partial<User>) => {
return UserGenerator.generate(userData);
});
// Jest时间Mock
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
// 测试中的时间控制
it('should execute callback after delay', () => {
const callback = jest.fn();
setTimeout(callback, 1000);
// 快进时间
jest.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalled();
});
// Vitest时间Mock
import { vi } from 'vitest';
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
// 错误Mock生成器
class ErrorMockGenerator {
static generateNetworkError(): Error {
const error = new Error('Network Error');
error.name = 'NetworkError';
error.code = 'NETWORK_ERROR';
return error;
}
static generateTimeoutError(): Error {
const error = new Error('Request timeout');
error.name = 'TimeoutError';
error.code = 'TIMEOUT';
return error;
}
static generateValidationError(field: string): Error {
const error = new Error(`Validation failed for field: ${field}`);
error.name = 'ValidationError';
error.field = field;
return error;
}
}
// 使用错误Mock
mockApi.getUser.mockRejectedValue(ErrorMockGenerator.generateNetworkError());
// 异步操作Mock
const asyncMock = jest.fn();
asyncMock
.mockResolvedValueOnce('first call result')
.mockRejectedValueOnce(new Error('second call error'))
.mockResolvedValueOnce('third call result');
// Promise链测试
it('should handle promise chain', async () => {
const result = await promiseChain();
expect(result).toBe('final result');
expect(asyncMock).toHaveBeenCalledTimes(3);
});
development
Vue 3 开发最佳实践指南 - Composition API、Script Setup、Pinia、TypeScript 集成及性能优化。 当用户说"Vue 3组件"、"Composition API"、"script setup"、"Pinia"、"Vue 3项目"、"ref reactive"、"defineProps defineEmits"、"Composable"、"Vue 3优化"时使用此技能。 涵盖:Script Setup 与 Composition API、响应式数据选择(ref vs reactive)、组件通信(Props/Emits/v-model/Slots)、Composables 设计模式、Pinia Setup Store、性能优化(v-memo、shallowRef、KeepAlive)。 提供 TypeScript 代码示例、反模式对照表、迁移指南和示例文件引用。
development
Vue 2 维护与开发最佳实践指南 - Options API、Vuex 及向 Vue 3 迁移准备。 当用户说"Vue 2组件"、"Options API"、"Vuex"、"Vue 2项目"、"Vue 2迁移"、"Vue mixin"、"Vue 2最佳实践"时使用此技能。 涵盖:Options API 规范(选项顺序、props 验证)、Vuex 模块化(namespaced modules)、逻辑复用(避免 mixin,使用工具函数)、迁移准备(停止使用 Filters、引入 Composition API 插件)。 提供 Vue 2 代码示例、反模式警告和迁移建议。
development
核心设计能力 - 提供配色、布局、组件样式生成及反模式检查。 当用户说"设计UI"、"生成样式"、"页面布局"、"CSS样式"、"组件设计"、"配色方案"、"设计系统"、"前端样式"、"响应式设计"、"动画效果"时使用此技能。 支持多种设计风格:Neo-Brutalism、Glassmorphism、Editorial、Cyberpunk。 提供配色方案、布局生成、组件样式、微交互动效、响应式网格。拒绝"AI廉价感",追求大胆、独特、细节丰富的设计。 重要特性:提供反模式检查,避免泛滥的渐变、无聊的阴影、默认圆角等平庸设计。
content-media
无障碍设计审查与修复能力。 当用户说"无障碍"、"a11y"、"WCAG"、"键盘导航"、"屏幕阅读器"、"颜色对比度"、"ARIA"、"可访问性"、"辅助功能"、"盲人友好"时使用此技能。 基于 WCAG 2.1 标准,检测图片 Alt 文本缺失、表单 Label 关联、键盘可访问性、颜色对比度不足、ARIA 属性误用等问题。 提供修复代码示例:语义化标签、焦点管理、焦点陷阱、屏幕阅读器支持。输出合规性检查报告和修复建议。