使用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的回调里测试才是有效的。

posted @ 2020-01-19 11:11  jim520  阅读(1415)  评论(0编辑  收藏  举报