返回
import { mount } from 'enzyme';
import Foo from './Foo';
describe('<MyComponent />', () => {
it('renders <Foo /> components', () => {
const props = {
visible:true,
onSubmit:jest.fn()
}
const wrapper = mount(<MyComponent {...props}/>);
//TODO 测试代码
});
})
//判断 Foo 渲染的个数
expect(wrapper.find(Foo).length).toBe(1);
//判断 Foo 被渲染
expect(wrapper.find(Foo).exists()).toBeTruthy();
//判断 Foo 的文本
expect(wrapper.find(Foo).text()).toMatch('hello world');
//判断 Foo 的渲染 html
expect(wrapper.find(Foo).html()).toMatch('<div className="foo">');
// 当同一个组建中,有多个Foo时
const foos = wrapper.find(Foo)
const foo1 = foos.at(0)
const foo2 = foos.at(1)
//判断 dom .foo 是否有类.foo1
expect(wrapper.find('foo').hasClass('foo1')).toBeFalsy();
//判断 wrapper 的 visible
expect(wrapper.prop('visible')).toBeTruthy()
//获取Foo 的 所有 props
const propsObj = wrapper.find(Foo).props()
//判断 Foo 的 属性 disabled
expect(propsObj['disabled']).toBeFalsy();
示例:mock antd 组建
代码
import {message} from 'antd'
message.error('请求失败')
测试
import * as antd from 'antd'
//mock 指定方法
const messageMock = jest.spyOn(antd.message,'error')
// 测试是否正确执行
expect(messageMock).toBeCalledWith('请求失败!')
//获取Foo Dom
const dom = wrapper.find(Foo)
//触发 Foo 的click 方法
dom.simulate('click')
//获取Foo Dom
const dom = wrapper.find(Foo)
//触发 Foo 的 属性方法 onSubmitHandle
dom.prop('onSubmitHandle')()
//针对当前整个组建,通过组建实例 instance() 执行某个函数
wrapper.instance().onSubmitHandle()
// 该方法一定是mock方法,才可以判断
// 执行方法
wrapper.prop('onSubmit')('hello')
// 判断方法是否执行
expect(props.onSubmit).toBeCalled()
expect(props.onSubmit).toBeCalledWith('hello')
expect(function).toThrowError()
备注:函数式组件,无法使用wrapper.setState()
// 修改属性 visible
wrapper.setProps({
'visible':false
})
// 必要时执行 更新
wrapper.update()
// 判断 visible 是否
expect(wrapper.prop('visible')).toBeFalthy()
// 修改state
wrapper.setState({
'aaa':false
})
// 必要时执行 更新
wrapper.update()
// 判断 state.aaa 是否
expect(wrapper.state('aaa')).toBeFalthy()
// 1、mock 请求方法
import * as Service from '../../service.ts'
const flushPromises = () => Promise.resolve()
const errorService = () => {
const data = {
response:{
status:412,
data:'error 412'
}
}
return Promise.reject(data)
}
const successService = () => {
const data = {
status:200,
data:[{
a:'1'
}]
}
return Promise.resolve(data)
}
//成功情况
jest.spyOn(service,'getInfoQuery').mockReturnValue(successService())
//失败情况
jest.spyOn(service,'getInfoQuery').mockReturnValue(errorService())
// 方法执行,需要 放在 it 为 async 的异步方法里
// 2、方法执行后,设置 await 等待请求返回
await flushPromises()
// 3、判断成功 or 失败时,响应的 dom、属性值、方法触发 变化情况
jest.useFakeTimers()
// 执行所有 定时任务
jest.runAllTimers()
// 执行当前第一个 定时任务
jest.runOnlyPendingTimers()
// 执行一段时间的 定时任务
jest.advanceTimersByTime(1000)
global.window = Object.create(window);
const url = "http://dummy.com";
Object.defineProperty(window, 'location', {
value: {
href: url
}
});
expect(window.location.href).toEqual(url);
连续的两个it测试,第二个it会继承使用第一个it的相同mock的数据
解决方法:
在第二个it 开始之前重置相同的mock方法
mockfn.mockReset()
// tests/setup.js
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
jest.config.js
module.exports = {
"setupFiles": ['<rootDir>/tests/setup'],
"preset": "ts-jest",
"verbose": true,
"testRegex": "./src/.*.spec.(t|j)sx?$",
"transform": {
"^.+\\.(j|t)sx?$": "ts-jest",
"^.+\\.(css|png)$": "jest-transform-stub",
},
"moduleNameMapper": {
"^@/(.*)$": "<rootDir>/src/$1",
"\\.(css|less)$": 'identity-obj-proxy',
"\\.(jpg|png|jpeg|svg|gif|otf|webp|eot|ttf|woff|woff2|mp4)$": '<rootDir>/tests/__mock__/fileMock.js',
},
"testPathIgnorePatterns": ['/node_modules'],
"moduleFileExtensions": [
"js",
"json",
"ts",
"tsx",
],
// 支持源代码中相同的 `@` -> `src` 别名
"collectCoverage": true,
"collectCoverageFrom": [
"./src/components/**/*.{js,tsx,ts}",
"./src/pages/**/*.{js,tsx,ts}",
"./src/utils/**/*.{js,ts}",
"./src/store/reducers/**/*.{js,ts}",
],
"coverageThreshold": {
global: {
statements: 0,
branches: 0,
functions: 0,
lines: 0,
}
},
"globals": {
'ts-jest': {
'diagnostics': false,
'tsConfig': '<rootDir>/tsconfig.test.json'
}
}
}
tests/mock/fileMock.js
module.exports = 'test-file-stub'
1、参考API:
[jest测试react](https://jestjs.io/docs/zh-Hans/tutorial-react)
[enmyze](https://airbnb.io/enzyme/docs/api/ReactWrapper/update.html)
2、 enmyze 测试 redux
https://hackernoon.com/unit-testing-redux-connected-components-692fa3c4441c
https://www.npmjs.com/package/enzyme-redux
npm install redux-mock-store --save-dev
3、enmyze react测试错误,
3.1 如果包含--prompt,则不能使用 mount 和 wrapper.html(),回报错
3.2 如果包含connect,则把class单独导出进行测试