【问题标题】:How to test a function that you don't have direct access to如何测试您无法直接访问的功能
【发布时间】:2020-11-23 22:56:40
【问题描述】:

我正在尝试测试从 useReducer 解构的 dispatch 函数。

我的调度函数是在我的组件中创建的,所以据我所知,我无法像往常一样expect(dispatch).toHaveBeenCalledWith({...})

我的组件看起来像这样:

const reducer = (state, action) => {
    switch (action.type) {
        case 'MY_ACTION':
            return { ...state, myError: action.payload };
    }
};

const Container = ({ someProp, anotherProp, aThirdProp }) => {

    // This hook only works at this level of my application

    const onlyAvailableInsideContainer = useonlyAvailableInsideContainer();



    // Due to the above my initial state needs to be created here

    const initialState = {
        initialStateArr: [],
        someProp,
        myError: null,
        aThirdProp,
        anotherProp,
        onlyAvailableInsideContainer,
    };



    // Which means I need to extract my state and dispatch functions within the Container also

    const [state, dispatch] = useReducer(reducer, initialState);

    const { fieldProps, formProps, errors } = someHook(
        hookConfig(state, dispatch, aThirdProp, onlyAvailableInsideContainer),
    );

    return (
        <div className="dcx-hybrid">
            <MyContext.Provider
                value={{ state, dispatch, fieldProps, formProps, errors }}
            >
                <SomeChildComponent />
            </MyContext.Provider>
        </div>
    );
};

我需要测试从useReducer 解构的调度函数,但我无法访问它(据我所知)。

理想情况下,我的初始状态和 useReducers 将专门从我的组件创建,但我需要只能从内部访问的信息。

这样的事情是我认为我需要做的,但我不知道如何以它知道我想要做什么的方式格式化测试。

function renderContainer(props) {
    // eslint-disable-next-line react/jsx-props-no-spreading
    const utils = render(<Container {...props} />);

    return {
        ...utils,
    };
}

test('an error will be disatched when the endpoint returns a 4xx status', async () => {
    fetchMock.post('/api/myendpoint', 400);

    const component = renderContainer();

    await act(async () => {
        fireEvent.click(component.getByText('Continue'));
    });

    expect(dispatch).toBeCalledWith({
        type: 'MY_ACTION',
        payload: 'Some error message.',
    });
});

【问题讨论】:

  • 测试调用的结果,而不是调用本身。
  • @HereticMonkey 我已经完成了 - 我的问题是我的覆盖率表中仍然缺少行:(
  • 你是怎么做到的?漏掉了哪些线?
  • @jonrsharpe 与上述方式非常相似。我检查是否存在呈现点击后/调度的元素。但是对于实际情况,我的减速器中仍然有未覆盖的线条
  • 只要确保您的测试对函数执行所有可能的输入,或者在您的情况下,对父函数的所有输入生成子函数的可能输入。

标签: javascript reactjs jestjs react-testing-library


【解决方案1】:

尝试像这样监视useReducer

const dispatch= jest.fn();
const useReducerMock= (reducer,initialState) => [initialState, dispatch];
jest.spyOn(React, 'useReducer').mockImplementation(useReducerMock);

然后测试它:

   expect(dispatch).toBeCalledWith({
        type: 'MY_ACTION',
        payload: 'Some error message.',
    });

【讨论】:

  • 我强烈建议不要监视 React 的某些部分——不要嘲笑你不拥有的东西。
  • @jonrsharpe 你是对的,但他想测试函数调用,最好测试这个动作的 ui。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-17
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
  • 2010-11-17
  • 2014-04-12
相关资源
最近更新 更多