【问题标题】:React and jest mock moduleReact 和 jest 模拟模块
【发布时间】:2017-02-23 19:10:42
【问题描述】:

我正在创建一个应用程序,在该应用程序中我使用 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()) 行为,并且我拥有 node-fetch 给出的默认解决承诺,而不是我用 Jest 模拟的承诺和用茉莉花窥探。

你知道什么是行不通的吗?

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

【问题讨论】:

    标签: javascript unit-testing reactjs jasmine jestjs


    【解决方案1】:

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

    我认为您需要创建一个模拟 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}}),
    

    另一方面,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 只是返回一个承诺。

    【讨论】:

      猜你喜欢
      • 2019-12-26
      • 2019-08-15
      • 2019-08-17
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      • 2021-02-04
      • 1970-01-01
      相关资源
      最近更新 更多