name: jest-generator description: 为JavaScript/TypeScript生成带有Mocking和覆盖率的Jest单元测试。适用于JS/TS模块、React组件、测试生成,或遇到缺失覆盖率、不当Mocking、测试结构错误时使用。 allowed-tools: 读、写、编辑、Bash、Grep、Glob
Jest生成器技能
目的
为JavaScript和TypeScript代码生成基于Jest的单元测试,遵循Jest惯例和最佳实践,包括适当的Mocking、describe块和代码组织。
何时使用
- 为JavaScript/TypeScript模块生成Jest测试
- 为React组件创建测试文件
- 为现有代码添加缺失的测试覆盖率
- 需要Jest特定模式(Mocking、间谍、快照)
测试文件命名
源文件到测试文件映射:
src/components/Feature.tsx→src/components/Feature.test.tsxsrc/utils/validator.ts→src/utils/validator.test.tssrc/models/User.ts→src/models/User.test.ts
运行测试
# 首选:使用bun(更快)
bun test
# 运行特定文件
bun test src/utils/validator.test.ts
# 运行带覆盖率
bun test --coverage
# 监视模式
bun test --watch
# 替代:使用npm
npm test
npm test -- --coverage
Jest测试结构
import { functionToTest, ClassToTest } from './Feature'
jest.mock('./dependency')
describe('模块名称', () => {
beforeEach(() => {
jest.clearAllMocks()
})
afterEach(() => {
jest.restoreAllMocks()
})
describe('类名', () => {
let instance: ClassToTest
beforeEach(() => {
instance = new ClassToTest()
})
it('使用有效输入时应返回预期结果', () => {
// 安排
const input = { key: 'value' }
const expected = { processed: true }
// 行动
const result = instance.method(input)
// 断言
expect(result).toEqual(expected)
})
it('使用无效输入时应抛出错误', () => {
expect(() => instance.method(null)).toThrow('无效输入')
})
})
})
Jest特定模式
Mocking
// Mock整个模块
jest.mock('./api', () => ({
fetchData: jest.fn(),
}))
// Mock带实现
const mockFn = jest.fn((x: number) => x * 2)
// 间谍方法
const spy = jest.spyOn(obj, 'method').mockReturnValue('mocked')
spy.mockRestore()
异步测试
it('应解析数据', async () => {
const result = await asyncFunction()
expect(result).toBeDefined()
})
it('应拒绝错误', async () => {
await expect(asyncFunction()).rejects.toThrow('错误')
})
定时器
beforeEach(() => jest.useFakeTimers())
afterEach(() => jest.useRealTimers())
it('应在超时后执行', () => {
const callback = jest.fn()
setTimeout(callback, 1000)
jest.advanceTimersByTime(1000)
expect(callback).toHaveBeenCalled()
})
常见匹配器
// 相等性
expect(value).toBe(expected)
expect(value).toEqual(expected)
// 真实性
expect(value).toBeTruthy()
expect(value).toBeNull()
expect(value).toBeDefined()
// 数组/对象
expect(array).toContain(item)
expect(obj).toHaveProperty('key')
// 函数/承诺
expect(fn).toThrow('错误')
await expect(promise).resolves.toBe(value)
// Mock函数
expect(mockFn).toHaveBeenCalled()
expect(mockFn).toHaveBeenCalledWith(arg)
React组件测试
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import { Button } from './Button'
describe('按钮', () => {
it('点击时应调用onClick', () => {
const handleClick = jest.fn()
render(<Button onClick={handleClick}>点击我</Button>)
fireEvent.click(screen.getByText('点击我'))
expect(handleClick).toHaveBeenCalledTimes(1)
})
})
质量检查清单
- [ ] 测试文件正确命名(
<模块>.test.ts) - [ ] 所有导出的函数/类已测试
- [ ] 包括正常路径和边缘情况
- [ ] 测试错误条件
- [ ] Mock外部依赖
- [ ] 测试用describe块组织
- [ ] beforeEach/afterEach用于设置/清理
- [ ] 描述性测试名称
- [ ] 覆盖率 ≥ 80%
最佳实践
- 使用描述性测试名称:
当<条件>时,应<预期> - 用describe块组织
- 仅Mock外部依赖
- 为组件测试用户行为
- 使用test.each进行参数化测试
- 保持测试独立
- 测试错误条件
- 目标覆盖率80%以上