如何使用 Jest 测试动作创建者创建的动作(而不是作为道具传递)是否触发?

How to test with Jest whether action created by action creator (and not passed as prop) fires?

我尝试测试给定的操作是否真的在组件中触发。如果带有动作的回调作为道具传递,这可能很容易,但我不清楚如何在我的案例中做到这一点。这是组件:

export const Modal = (props: appendProps): JSX.Element => {
    const { items, activeScope } = props;
    const primary = items[0] === activeScope;
    const { closeInput, appendItem } = useDispatchAction();
{...}
    <Button
      variant="contained"
      size="large"
      className="modal-content__button"
      color="secondary"
      onClick={() => {
           closeInput();
      }}
      >
       Zamknij
   </Button>

useDispatchAction 如下:

import { useDispatch } from 'react-redux';
import { bindActionCreators } from 'redux';
import { actionCreators } from '../redux';

const useDispatchAction = () => {
    const dispatch = useDispatch();
    return bindActionCreators(actionCreators, dispatch);
};

export default useDispatchAction;

并在下方进行自我测试

describe('Test button actions', () => {
    const closeInput = jest.fn();
    jest.mock('../../src/hooks/useDispatchAction', () => ({closeInput}));

    beforeEach(() => {
        render(<Modal />);
    });
    afterEach(() => cleanup());
    test('component fires closeInput', () => {
        const closeButton = screen.getByRole('button', { name: 'Zamknij' });
        expect(closeButton).toBeInTheDocument();
        userEvent.click(closeButton);
        expect(closeInput).toBeCalled();
    });
});

但这一直告诉我函数被调用了 0 次,至少不是 1 次

当您 jest.mock 时,您会得到一个 return 默认情况下 undefined 的函数。所以,如果 useDispatchAction returns undefined,你不能去 const { closeInput, appendItem } = useDispatchAction();,因为你不能从 undefined.

解构

但是,您可以 supply a second argumentjest.mock:

const closeInput = jest.fn()
jest.mock('../../src/hooks/useDispatchAction', () => ({ closeInput }))

现在您已将 useDispatchAction 模拟为 return 看起来更像您的原始函数的东西,除了调用了您可以断言的操作 return 之外。

你可以这样测试:

expect(closeInput).toHaveBeenCalled()

我认为这应该可行,但我尚未测试此特定代码。

最终起作用的是:

const actions = {
    closeInput: jest.fn(),
    appendItem: jest.fn(),
};

jest.mock('../../src/hooks/useDispatchAction', () => () => actions);

describe('Given Modal component', () => {
    describe('when "Zamknij" button is clicked', () => {
        it('should call closeInput function', async () => {
            actions.closeInput.mockClear();

            const { findByText } = render(<Modal />);
            const closeButton = await findByText('Zamknij');

            fireEvent.click(closeButton);

            expect(actions.closeInput).toHaveBeenCalled();
        });
    });
});