元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
TypeScript环境准备
安装与配置
第一个TS程序
编译流程解析
▶
基础类型系统
类型注解语法
原始类型定义
数组与元组
接口与对象
▶
高级类型系统
泛型编程
条件类型
映射类型
类型推断
类型保护
高级类型工具
▶
函数开发
函数类型声明
可选参数与默认值
箭头函数应用
函数重载
泛型函数
▶
类与面向对象
类的定义
继承与修饰符
存取器使用
抽象类与接口
泛型类与抽象类
访问修饰符与属性
▶
模块化开发
模块导入导出
类型声明文件
命名空间
模块解析策略
▶
工程实践
tsconfig详解
常见编译选项
项目构建配置
代码组织最佳实践
单元测试
调试技巧
▶
常见问题
类型错误处理
类型断言技巧
类型兼容性
版本迁移指南
发布时间:
2025-03-31 09:51
↑
☰
# TypeScript单元测试 本文将详细介绍如何在TypeScript项目中进行单元测试,包括测试框架的选择、测试用例的编写、测试覆盖率的统计等内容。 ## 常用测试框架 ### 1. Jest 最流行的JavaScript测试框架,对TypeScript有很好的支持: ```bash # 安装Jest和相关依赖 npm install --save-dev jest @types/jest ts-jest ``` 配置Jest支持TypeScript: ```json // jest.config.js module.exports = { preset: 'ts-jest', testEnvironment: 'node', roots: ['<rootDir>/src'], testMatch: ['**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)'], moduleNameMapper: { '^@/(.*)$': '<rootDir>/src/$1' } }; ``` ### 2. Mocha + Chai 另一个流行的组合: ```bash # 安装Mocha、Chai及其类型定义 npm install --save-dev mocha chai @types/mocha @types/chai ts-node ``` 配置Mocha: ```json // .mocharc.json { "extension": ["ts"], "spec": "src/**/*.spec.ts", "require": "ts-node/register" } ``` ## 编写测试用例 ### 1. 基础测试 ```typescript // math.ts export function add(a: number, b: number): number { return a + b; } // math.test.ts import { add } from './math'; describe('Math functions', () => { it('should add two numbers correctly', () => { expect(add(1, 2)).toBe(3); expect(add(-1, 1)).toBe(0); expect(add(0, 0)).toBe(0); }); }); ``` ### 2. 异步测试 ```typescript // user.service.ts export class UserService { async getUser(id: number): Promise<User> { // API调用 } } // user.service.test.ts describe('UserService', () => { it('should fetch user data', async () => { const service = new UserService(); const user = await service.getUser(1); expect(user).toBeDefined(); expect(user.id).toBe(1); }); }); ``` ### 3. Mock和Stub ```typescript // 使用Jest的Mock功能 jest.mock('./api'); describe('UserService', () => { beforeEach(() => { jest.clearAllMocks(); }); it('should handle API error', async () => { const mockError = new Error('API Error'); api.getUser.mockRejectedValue(mockError); await expect(service.getUser(1)).rejects.toThrow(mockError); }); }); ``` ## 测试覆盖率 ### 1. 配置覆盖率报告 ```json // jest.config.js module.exports = { collectCoverage: true, coverageDirectory: 'coverage', coverageReporters: ['text', 'lcov'], coverageThreshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80 } } }; ``` ### 2. 忽略测试覆盖 ```typescript /* istanbul ignore next */ function debugLog(message: string): void { console.log(message); } ``` ## 测试最佳实践 ### 1. 测试文件组织 ``` src/ ├── components/ │ ├── Button/ │ │ ├── Button.tsx │ │ ├── Button.test.tsx │ │ └── Button.stories.tsx └── utils/ ├── math.ts └── math.test.ts ``` ### 2. 测试命名规范 ```typescript describe('UserService', () => { describe('getUser', () => { it('should return user when valid id is provided', () => { // 测试代码 }); it('should throw error when user not found', () => { // 测试代码 }); }); }); ``` ### 3. 测试隔离 ```typescript describe('UserService', () => { let service: UserService; let mockDb: jest.Mocked<Database>; beforeEach(() => { mockDb = { query: jest.fn(), connect: jest.fn() }; service = new UserService(mockDb); }); afterEach(() => { jest.clearAllMocks(); }); }); ``` ## 常见测试场景 ### 1. 组件测试 ```typescript import { render, fireEvent } from '@testing-library/react'; describe('Button', () => { it('should handle click events', () => { const handleClick = jest.fn(); const { getByText } = render( <Button onClick={handleClick}>Click Me</Button> ); fireEvent.click(getByText('Click Me')); expect(handleClick).toHaveBeenCalled(); }); }); ``` ### 2. Hook测试 ```typescript import { renderHook, act } from '@testing-library/react-hooks'; describe('useCounter', () => { it('should increment counter', () => { const { result } = renderHook(() => useCounter()); act(() => { result.current.increment(); }); expect(result.current.count).toBe(1); }); }); ``` ### 3. API测试 ```typescript import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; describe('API', () => { const mock = new MockAdapter(axios); afterEach(() => { mock.reset(); }); it('should fetch users', async () => { const users = [{ id: 1, name: 'John' }]; mock.onGet('/api/users').reply(200, users); const response = await api.getUsers(); expect(response.data).toEqual(users); }); }); ``` ## 调试测试 ### 1. 使用Debug模式 ```json // package.json { "scripts": { "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand" } } ``` ### 2. 测试快照 ```typescript describe('Component', () => { it('should match snapshot', () => { const { container } = render(<MyComponent />); expect(container).toMatchSnapshot(); }); }); ``` ## 总结 良好的单元测试可以: - 提高代码质量 - 防止回归错误 - 简化重构过程 - 提供代码文档 建议: 1. 从简单的测试开始 2. 保持测试代码的可维护性 3. 定期运行测试 4. 持续优化测试覆盖率 5. 结合CI/CD流程