Как протестировать функцию, к которой у вас нет прямого доступа - PullRequest
2 голосов
/ 03 августа 2020

Я пытаюсь протестировать функцию dispatch, деструктурированную из useReducer.

Моя функция диспетчеризации создана в моем компоненте, поэтому, насколько я могу судить, я не могу 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.',
    });
});

1 Ответ

0 голосов
/ 04 августа 2020

попробуйте шпионить за 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.',
    });
...