首页 > 解决方案 > Typescript,在 Redux 操作中测试 Api 调用,在 Enzyme 中模拟类,Jest

问题描述

我有一个问题,我需要模拟一个Api在我的 redux 操作中调用的类,这个类调用 axios get、post 等......需要模拟。我一直在关注教程,解释如何模拟 axios 和教程关于如何模拟类,但两种方法似乎都不起作用。

现在有一些代码......这是我需要测试的操作类型的示例。

export const getAlldata = (id: string) => {
    return (dispatch: any) => {
        dispatch(beginAjaxRequest(id, types.BEGIN_GET_DATA_AJAX));
        return Api.get("/data/data").then((response: any) => {
            dispatch(getDataSuccess(response.data, id))
        }).catch((error) => {
            dispatch(handleAjaxError(id, new Alert({ id: id, title: "Error getting data", message: error.toString(), timestamp: Date.now(), error: true })));
        });
    }
}

Api这个电话的部分。

import axios from 'axios';

class Api {
    static get(path: string) {
        return axios({
            method: 'get',
            url: (global as any).apiDomain + path,
            headers: {
                Authorization: "Bearer " + (global as any).authentication.getToken(),
            "Content-Type": "application/json"
            }
        });
    }
}

export default Api;

我试图在 src/mocks/Api 中模拟(模拟前后两个下划线)

import * as Promise from 'bluebird';
import { getTestData } from '../models/_tests/TestData';

class Api {
    static get(path: string) {
        switch (path) {
            case "/data/data":
                return Promise.resolve({
                    data: getTestData(3)
                });
            default:
                return {};
        }
    }
}

export default Api;

并在我的 setupTests 中设置。

import * as Enzyme from 'enzyme';
import Api from './__mocks__/Api';
const Adapter = require("enzyme-adapter-react-16");

(global as any).Api = Api;

Enzyme.configure({ adapter: new Adapter() });

并在我的实际测试中调用...

describe('thunk actions', () => {

    var middleware = [thunk];
    var mockStore = configureMockStore(middleware);
    afterAll(() => {
        cleanAll();
    });

    test('getAllData gets all data', (done: any) => {
        var store = mockStore({});
        jest.mock('../../api/Api'); // path to real Api
        var id = generateGuid();
        store.dispatch<any>((getAllData(id))).then(() => {
            done();
        });
    });
});

所以显然这实际上并没有测试任何东西,我只是想让它工作,但我一直在真正的 Api 而不是模拟中遇到错误。我也尝试过模拟 axios,但我得到了同样的错误(无法 getToken of undefined)所以这似乎并没有取代 axios 或 Api,任何人都可以看到我哪里出错了?

标签: reactjstypescriptunit-testingreact-reduxjestjs

解决方案


您知道,当您将问题发布到 stackoverflow 并在一周内获得 0 个答案和 0 个响应时,您会被搞砸……并不理想,但我找到了一种解决方法,可以在我的 thunk 操作中覆盖 Api 类,而不是导入Api 类到我的所有操作文件中并直接调用它,我现在只将它导入我的项目的根目录(App.tsx)并使其成为全局如下(精简到最低限度)。

import * as React from 'react';
import Api from './api/Api';

export interface State {

}

export interface Props {

}

export class App extends React.Component<Props, State> {

    state = {

    };

    componentWillMount = () => {
        (global as any).Api = Api;
    };





    public render() {
        return (
            <div>

            </div>
        );
    }
}


export default App;

...然后在我的 thunk 操作上调用 Api,如下所示

export const getAlldata = (id: string) => {
    return (dispatch: any) => {
        dispatch(beginAjaxRequest(id, types.BEGIN_GET_DATA_AJAX));
        return (global as any).Api.get("/data/data").then((response: any) => {
            dispatch(getDataSuccess(response.data, id))
        }).catch((error) => {
            dispatch(handleAjaxError(id, new Alert({ id: id, title: "Error getting data", message: error.toString(), timestamp: Date.now(), error: true })));
        });
    }
}

然后简单地覆盖这是 setupTests.ts

import * as Enzyme from 'enzyme';
import Api from './__mocks__/Api';
const Adapter = require("enzyme-adapter-react-16");

(global as any).Api = Api;

Enzyme.configure({ adapter: new Adapter() });

...然后就不需要开玩笑了,只需调用测试中的动作并进行测试。

通过将 global 替换为 window,此方法也可以在 Node 之外工作。这可以完成工作,但并不理想,因为我不喜欢使用全局命名空间,所以如果有人知道更好的方式发布。


推荐阅读