使用axios-mock-adapter对axios请求进行mock
在使用jest和enzyme对react进行单元测试时,如果我们需要对axios的请求进行测试,可以使用axios-mock-adapter。
这里只是拿单元测试举例,正常逻辑里的mock也可以使用,但是既然单元测试都通过了正常逻辑里不用也无所谓了(因为正常逻辑里加了后面也得删...)。
vSwitch.ui.jsx代码如下:(看黄色部分即可)
import React, { useState, useEffect } from "react";
import axios from '../../../request';
import { Form, Input, Select } from 'antd';
import { FetchAvailabilityZoneURL } from "../url";
const { Option } = Select;
const TextArea = Input.TextArea;
const ReactRender = (props) => {
const { type, cellId, db } = props;
const { getFieldDecorator } = props.form;
const doc = db.getDoc(type, cellId);
const vpcDoc = db.getDocByRefId(doc.vpc_id);
let vpcName = vpcDoc.name;
const onSubmit = (e) => {
e.preventDefault();
props.form.validateFields((err, values) => {
if (!err) {
// 所属vPC始终要用vpc_id的值保存
values.vpc_id = doc.vpc_id;
db.updateDoc(type, cellId, values);
}
});
};
let [allData, setData] = useState(() => {
return { availabilityZoneData: [] };
});
useEffect(() => {
axios.post(FetchAvailabilityZoneURL, { "multi": true })
.then((response) => {
const availabilityZoneData = response.data.ids;
setData(allData => ({
...allData,
availabilityZoneData
}));
}).catch((error) => {
});
}, []);
return (
<Form onChange={onSubmit} onClick={onSubmit}>
<Form.Item label="名称">
{getFieldDecorator('name', {
initialValue: doc.name,
rules: [{ required: true, message: '请填写名称' }],
})(<Input />)}
</Form.Item>
<Form.Item label="描述">
{getFieldDecorator('description', {
initialValue: doc.description
})(<TextArea rows={5} />)}
</Form.Item>
<Form.Item label="所属vPC">
<React.Fragment>
{getFieldDecorator('vpc_id', {
initialValue: vpcName,
rules: [{ required: true, message: '自动关联vPC' }],
})(<Input hidden />)}
<span>{vpcName}</span>
</React.Fragment>
</Form.Item>
<Form.Item label="IPv4地址范围">
{getFieldDecorator('cidr_block', {
initialValue: doc.cidr_block,
rules: [{
required: true, message: '请填写IPv4地址范围'
}, {
pattern: /^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$/,
message: '请填写正确的CIDR(如:192.168.11.0/16)'
}],
})(<Input />)}
</Form.Item>
<Form.Item label="可用区">
{getFieldDecorator('availability_zone', {
initialValue: doc.availability_zone || undefined,
rules: [{ required: true, message: '请选择可用区' }],
})(
<Select
showSearch
style={{ width: '100%' }}
placeholder="请选择可用区"
optionFilterProp="children"
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{
allData.availabilityZoneData && allData.availabilityZoneData.map(item =>
<Option key={item} value={item}>{item}</Option>
)
}
</Select>
)}
</Form.Item>
</Form>
)
};
export default Form.create()(ReactRender);
vSwitch.test.jsx代码如下:(看黄色部分即可)
import MockAdapter from "axios-mock-adapter"; import axios from "../../../request"; import VSwitch from "../component/vSwitch"; import { mount } from 'enzyme'; import { FetchAvailabilityZoneURL } from "../url"; import { getDatabase, getGlobalID } from "../../../database"; describe("vSwitch测试", () => { const mock = new MockAdapter(axios); const vSwitch = new VSwitch(); const db = getDatabase(); // 模仿UI操作,添加一个cell,然后立即调用渲染方法 vSwitch.onAdd("alicloud_vswitch", { id: 1 }); const wrapper = mount(vSwitch.render("alicloud_vswitch", 1)); // 为select下拉框设置默认值 // const component = wrapper.dive(); wrapper.instance().setFieldsValue({ availability_zone: `cn-shanghai-a`, }); it('render', () => { const data = { ids: ["cn-shanghai-a", "cn-shanghai-b", "cn-shanghai-c", "cn-shanghai-d", "cn-shanghai-e", "cn-shanghai-f"] }; mock.onPost(FetchAvailabilityZoneURL).reply( (config) => { return new Promise(function (resolve, reject) { resolve([200, data]); }).then(() => { wrapper.find('#availability_zone .ant-select-selection__rendered').simulate('click'); expect(wrapper.find('.ant-select-dropdown-menu li').length).toBe(6); }); } ); expect(wrapper.find("FormItem").length).toBe(5); expect(wrapper.find("FormItem").first().props().label).toBe('名称'); expect(wrapper.find("FormItem").get(1).props.label).toBe('描述'); expect(wrapper.find("FormItem").get(2).props.label).toBe('所属vPC'); expect(wrapper.find("FormItem").get(3).props.label).toBe('IPv4地址范围'); expect(wrapper.find("FormItem").last().props().label).toBe('可用区'); }); it('onInParent', () => { const vpcCellId = 10; const vpcDoc = db.saveDoc("alicloud_vpc", vpcCellId, { name: "test", cidr_block: "10.10.0.0/16", description: "test" }); // 和vPC建立关系 const vpcCell = { data: { type: "alicloud_vpc", provider: "alicloud" }, id: vpcCellId }; vSwitch.onInParent("alicloud_vswitch", { id: 1 }, vpcCell); const vswtichDoc = db.getDoc("alicloud_vswitch", 1); expect(vswtichDoc.vpc_id).toBe(getGlobalID(vpcDoc)); }); it('onInputChange', () => { wrapper.find('input').at(0).simulate('change', { target: { value: "test_vswitch_name" } }); expect(wrapper.find('input').at(0).prop('value')).toBe('test_vswitch_name'); wrapper.find('input').at(1).simulate('change', { target: { value: "test_vpc_description" } }); expect(wrapper.find('input').at(1).prop('value')).toBe('test_vpc_description'); wrapper.find('input').at(3).simulate('change', { target: { value: "192.168.11.0/16" } }); expect(wrapper.find('input').at(3).prop('value')).toBe('192.168.11.0/16'); wrapper.find('#availability_zone .ant-select-selection__rendered').simulate('click'); wrapper.find('.ant-select-dropdown-menu li').at(0).simulate('click'); expect(wrapper.find('.ant-select-selection-selected-value').prop('title')).toBe('cn-shanghai-a'); }); it('onDelete', () => { // 删除alicloud_vswitch vSwitch.onDelete("alicloud_vswitch", { id: 1 }); const vswtichDoc = db.getDoc("alicloud_vswitch", 1); expect(vswtichDoc).toBeUndefined(); }); });
总的来说就是要在Promise的回调里测试才是有效的。

浙公网安备 33010602011771号