被测组件划分
展示组件:通常定义为只用于展示的组件,例如 Icon、Badge……,遵循 Props –> UI;
业务组件:为业务服务,通常集成了独立的功能,可以单独作为模块组件,也可自定义配置;
功能组件:通常是支撑业务组件的基类组件,提供一些功能性的支撑,像分页组件的跳转;
测试场景 网络请求模拟/发起真实请求
可以模拟封装网络请求的方法,借助jest.mock
模拟引用文件,返回需要结果的Promise
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import { mount } from 'enzyme' ;import App from 'Componets/app.jsx' ;import postData from '../api' ;jest.mock('../api' , () => jest.fn(() => Promise .then({data : { name : 'eric' , age : 18 }}))); describe('An Test Example' , () => { it('Should called if mount' , () => { const wrapper = mount(<App /> ); expect(postData).toBeCalledTimes(1 ); }); });
直接模拟真实请求,借助enzyme
断言回调的done
函数或者async
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import { mount } from 'enzyme' ;import fetchData from '../api' ;test('Test Fetch Data' , (done ) => { fetchData() .then(r => r) .finally(() => done()) }); test('Test Fetch Data' , async () => { try { const res = await fetchData(); } catch (e) { console .error(e); } });
根目录新建__mocks__
文件夹,内部新建request.js
,模拟用户请求。
测试异步请求其实还有其余的两种方案可以选择,像请求成功与请求失败:
1 2 3 4 5 6 7 8 9 jest.mock('../request' ); import * as user from '../user' ;it('works with promises' , () => { expect.assertions(1 ); return user.getUserName(4 ).then(data => expect(data).toEqual('Mark' )); });
1 2 3 4 it('works with resolves' , () => { expect.assertions(1 ); return expect(user.getUserName(5 )).resolves.toEqual('Paul' ); });
jest
测试环境之node
&browser
切换jest
默认browser
环境,如果需要切换node
环境,在顶部追加一段注释就可以了。
也可以自己内置沙盒去做为jest
预置环境。文档指引
定时器模拟 1 2 3 4 5 jest.useFakeTimers(); test('Test one timer unit case' , () => { jest.runAllTimers(); });
未实现模块模拟 诸如window
上的某些模块并未实现,像location
模块,我们可以借助node
环境的global
模块下去模拟一个纯净的模块。
像包中的peerDependences
我们可以借助,虚拟模块或者真实自定义模块模拟。
1 2 3 4 5 6 7 8 const user = jest.createMockFromModule('../user' );user.getAuthenticated = () => ({ age: 622 , name: 'Mock name' , }); export default user;
1 2 3 4 5 6 7 8 9 10 11 jest.mock( '../moduleName' , () => { }, {virtual : true }, );
小结 在观摩antd
的测试用例的时候,有看到过这样的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 it('not repeat render when Form.Item is not a real Field' , async () => { const shouldNotRender = jest.fn(); const StaticInput = () => { shouldNotRender(); return <Input /> ; }; const shouldRender = jest.fn(); const DynamicInput = () => { shouldRender(); return <Input /> ; }; const formRef = React.createRef(); mount( <div> <Form ref={formRef}> <Form.Item> <StaticInput /> </Form.Item> <Form.Item name="light" > <DynamicInput /> </Form.Item> </Form> </div>, ); expect(shouldNotRender).toHaveBeenCalledTimes(1 ); expect(shouldRender).toHaveBeenCalledTimes(1 ); formRef.current.setFieldsValue({ light : 'bamboo' }); await Promise .resolve(); expect(shouldNotRender).toHaveBeenCalledTimes(1 ); expect(shouldRender).toHaveBeenCalledTimes(2 ); });