一、Jest 配置
1. 基本配置
Jest 的配置通常可以在 package.json
文件中进行设置。以下是一个基本示例:
json
{
"jest": {
"testEnvironment": "jsdom",
"setupFilesAfterEnv": ["<rootDir>/setupTests.js"],
"moduleNameMapper": {
"\.(css|less)$": "identity-obj-proxy"
},
"coverageDirectory": "coverage",
"collectCoverage": true
}
}
2. 使用配置文件
也可以创建一个名为 jest.config.js
的文件,包含以下内容:
java
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/setupTests.js'],
moduleNameMapper: {
'\.(css|less)$': 'identity-obj-proxy',
},
coverageDirectory: 'coverage',
collectCoverage: true,
};
3. 运行时配置
在运行 Jest 时,可以使用命令行参数覆盖配置项。例如,使用 --watch
参数以观察模式运行测试:
css
jest --watch
4. 在 TypeScript 项目中使用 Jest
1. 安装必要的依赖
确保安装了 TypeScript、Jest 及其相关依赖:
css
npm install --save-dev jest ts-jest @types/jest
2. 创建 Jest 配置文件
创建一个 jest.config.js
文件,配置 Jest 使用 ts-jest
来处理 TypeScript 文件:
java
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node', // 或 'jsdom',根据项目需求选择
moduleNameMapper: {
'\.(css|less)$': 'identity-obj-proxy',
},
coverageDirectory: 'coverage',
collectCoverage: true,
};
3. TypeScript 配置
确保 tsconfig.json
文件包含适当的设置,特别是 esModuleInterop
和 skipLibCheck
选项:
json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true
},
"include": ["src/**/*", "test/**/*"]
}
二、实际应用案例
案例 1:React 组件测试
需求
测试一个简单的计数器组件,能够增加和减少计数。
组件代码
javascript
// Counter.js
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>Increase</button>
<button onClick={() => setCount(count - 1)}>Decrease</button>
</div>
);
};
export default Counter;
测试代码
使用 render
和 fireEvent
方法来测试组件的功能。
javascript
// Counter.test.js
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('initial count is 0', () => {
const { getByText } = render(<Counter />);
expect(getByText('0')).toBeInTheDocument();
});
test('increases count by 1 when Increase button is clicked', () => {
const { getByText } = render(<Counter />);
fireEvent.click(getByText('Increase'));
expect(getByText('1')).toBeInTheDocument();
});
test('decreases count by 1 when Decrease button is clicked', () => {
const { getByText } = render(<Counter />);
fireEvent.click(getByText('Increase'));
fireEvent.click(getByText('Decrease'));
expect(getByText('0')).toBeInTheDocument();
});
案例 2:API 测试
需求
测试一个异步函数,从 API 获取数据。
API 函数代码
javascript
// api.js
export const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
return response.json();
};
测试代码
使用 Mock 函数来模拟 API 响应。
javascript
// api.test.js
import { fetchData } from './api';
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: 'mock data' }),
})
);
test('fetches successfully data from an API', async () => {
const data = await fetchData();
expect(data).toEqual({ data: 'mock data' });
});
test('fetch fails with an error', async () => {
fetch.mockImplementationOnce(() => Promise.reject('API is down'));
await expect(fetchData()).rejects.toEqual('API is down');
});
案例 3:快照测试
组件代码
javascript
// Button.js
import React from 'react';
const Button = ({ label }) => (
<button>{label}</button>
);
export default Button;
测试代码
使用快照测试验证组件的输出。
javascript
// Button.test.js
import React from 'react';
import renderer from 'react-test-renderer';
import Button from './Button';
test('Button renders correctly', () => {
const tree = renderer.create(<Button label="Click me" />).toJSON();
expect(tree).toMatchSnapshot();
});
三、常用 API 和方法
1. 测试用例 API
test(name, fn)
:定义一个测试用例。it(name, fn)
:与test
等效,描述行为。
2. 匹配器
-
expect(value)
:用于断言某个值。 -
常用匹配器:
toBe(value)
:严格相等。toEqual(value)
:深度相等。toBeTruthy()
:值为真。toContain(item)
:检查数组或字符串中是否包含某个项。toMatchSnapshot()
:进行快照测试。
3. 异步匹配
resolves
:测试 Promise 的成功结果。rejects
:测试 Promise 的失败结果。
4. Mock 函数 API
jest.fn()
:创建一个新的 Mock 函数。mockReturnValue(value)
:设置 Mock 函数的返回值。mockImplementation(fn)
:设置 Mock 函数的实现。mock.calls
:获取 Mock 函数的调用记录。
5. 组装和清理 API
beforeEach(fn)
:在每个测试用例之前运行的函数。afterEach(fn)
:在每个测试用例之后运行的函数。beforeAll(fn)
:在所有测试用例之前运行的函数。afterAll(fn)
:在所有测试用例之后运行的函数。
6. 运行测试的命令
jest --watch
:以观察模式运行测试。jest --coverage
:生成代码覆盖率报告。