Typescript, тестирование Api-вызовов в действиях Redux, насмешливый класс в Enzyme, Jest - PullRequest
1 голос
/ 09 апреля 2019

У меня есть проблема, когда мне нужно издеваться над классом Api, который вызывается в моих действиях с избыточностью, этот класс вызывает axios get, post и т. Д. ..., которые должны быть смоделированы. Я следовал this tutorial explaining how to mock axios and этому учебнику о том, как издеваться над классом, но ни один из подходов не работает.

Теперь для некоторого кода ... вот пример типа действия, которое мне нужно проверить.

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 (два подчеркивания после и перед mock)

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;

и настройку в моих настройках.

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, но я получаю ту же ошибку (не могу получить toToken из undefined), так что, похоже, она не заменяет axios или Api, кто-нибудь может увидеть, где я ошибаюсь?

1 Ответ

1 голос
/ 16 апреля 2019

Вы знаете, что вы облажались, когда публикуете вопрос в stackoverflow и получаете 0 ответов и 0 ответов в течение недели ... Не идеально, но я нашел обходной путь, чтобы переопределить класс Api в моих действиях thunk, вместо этого импортируя класс 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;

... и затем вызовите 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() });

... и тогда не нужно шутить, просто вызывайте действия в ваших тестах и ​​тестируйте.

Этот метод также будет работать за пределами Node, заменив global на window. Это делает работу, но не идеально, так как я предпочитаю не использовать глобальное пространство имен, поэтому, если кто-нибудь знает лучший способ опубликовать сообщение.

...