React 和 jest 模拟模块

React and jest mock module

我正在创建一个应用程序,我在其中使用 redux 和 node-fetch 进行远程数据获取。

我想测试一下我是否使用正确的参数调用 fetch 函数。

这样,我正在使用 jest.mock 和 jasmine.createSpy 方法:

it('should have called the fetch method with URL constant', () => {
            const spy = jasmine.createSpy('nodeFetch');
            spy.and.callFake(() => new Promise(resolve => resolve('null')));
            const mock = jest.mock('node-fetch', spy);
            const slug = 'slug';
            actionHandler[FETCH_REMOTE](slug);
            expect(spy).toHaveBeenCalledWith(Constants.URL + slug);
        });

这是我要测试的功能:

[FETCH_REMOTE]: slug => {
        return async dispatch => {
            dispatch(loading());
            console.log(fetch()); // Displays the default fetch promise result
            await fetch(Constants.URL + slug);
            addLocal();
        };
    }

如您所见,我正在尝试记录 console.log(fetch()) 行为,并且我有默认承诺来解决节点获取给出的问题,而不是我已经用 Jest 模拟,用 jasmine 监视。

你知道它不起作用吗?

编辑:我的测试向我显示了一个错误,就像我的间谍从未被调用过

您的操作处理程序实际上是一个操作处理程序工厂。在 actionHandler[FETCH_REMOTE] 中,您正在创建一个新函数。返回的函数任务 dispatch 作为参数并调用您显示的代码。
这意味着您的测试代码永远不会调用间谍上的任何函数,因为永远不会调用创建的函数。

我认为您需要创建一个模拟 dispatch 函数并执行如下操作:

let dispatchMock = jest.fn(); // create a mock function
actionHandler[FETCH_REMOTE](slug)(dispatchMock);

编辑:

对我来说,你的 actionHandler 看起来更像是一个 actionCreator,因为它通常在 redux 术语中被称为,尽管我个人更喜欢称它们为 actionFactories 因为它们就是这样是:创建动作的工厂。
当您使用 thunks(?) 时,您的 actionCreater(误命名为 actionHandler)不会直接创建 action,而是会在操作后立即调用另一个函数被派遣。作为比较,常规的 actionCreator 看起来像这样:

updateFilter: (filter) => ({type: actionNames.UPDATE_FILTER, payload: {filter: filter}}),

A actionHandler 另一方面对正在调度的动作做出反应并评估它们的有效负载。

针对您的情况,我会这样做:

像这样创建一个名为 actionFactories 的新对象:

const actionFactories = {

    fetchRemote(slug): (slug) => {
        return async dispatch => {
            dispatch(loading());
            console.log(fetch()); // Displays the default fetch promise result
            let response = await fetch(Constants.URL + slug);

            var responseAction;
            if (/* determine success of response */) {
                responseAction = actionFactories.fetchSuccessful(response);
            } else {
                responseAction = actionFactories.fetchFailed();
            }

            dispatch(responseAction);
        };
    }

    fetchFailed(): () => ({type: FETCH_FAILED, }),
    fetchSuccessful(response): () => ({type: FETCH_FAILED, payload: response })
};

FETCH_FAILEDFETCH_SUCCESSFUL 创建 actionHandler 以根据响应更新商店。

顺便说一句:你的 console.log 声明对我来说也没有多大意义,因为 fetch 只是 returns 一个承诺。