如何使用 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 argument 到 jest.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();
});
});
});
我尝试测试给定的操作是否真的在组件中触发。如果带有动作的回调作为道具传递,这可能很容易,但我不清楚如何在我的案例中做到这一点。这是组件:
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 argument 到 jest.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();
});
});
});